diff --git a/src/api/index.ts b/src/api/index.ts index e1ca839a9..fb08d95ab 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -3,3 +3,4 @@ export * from './export'; export * from './keyring'; export * from './request'; export * from './response'; +export * from './transaction'; diff --git a/src/api/keyring.ts b/src/api/keyring.ts index de3b0bd13..c57f2b706 100644 --- a/src/api/keyring.ts +++ b/src/api/keyring.ts @@ -4,6 +4,7 @@ import type { KeyringAccount } from './account'; import type { KeyringAccountData } from './export'; import type { KeyringRequest } from './request'; import type { KeyringResponse } from './response'; +import type { Transaction } from './transaction'; /** * Keyring interface. @@ -44,6 +45,13 @@ export type Keyring = { */ createAccount(options?: Record): Promise; + /** + * List the transactions of an account. + * + * @param id - The ID of the account to list the transactions for. + */ + listAccountTransactions?(id: string): Promise; + /** * Filter supported chains for a given account. * diff --git a/src/api/transaction.ts b/src/api/transaction.ts new file mode 100644 index 000000000..375c49b4f --- /dev/null +++ b/src/api/transaction.ts @@ -0,0 +1,197 @@ +import type { Infer } from 'superstruct'; +import { array, enums, number, string } from 'superstruct'; + +import { object } from '../superstruct'; +import { UuidStruct } from '../utils'; + +/** + * This struct represents an asset. + * + * @example + * ```ts + * asset: { + * id: 'eip155:1/slip44:60', + * unit: 'ETH', + * }, + * ``` + */ +const AssetStruct = object({ + /** + * Asset ID (CAIP-19). + */ + id: string(), + + /** + * Unit of the asset. This has to be one of the supported units for the + * asset, as defined by MetaMask. + */ + unit: string(), +}); + +/** + * This struct represents an amount of an asset. + * + * @example + * ```ts + * fee: { + * amount: '0.01', + * asset: { + * id: 'eip155:1/slip44:60', + * unit: 'ETH', + * }, + * }, + * ``` + */ +const AmountStruct = object({ + /** + * Amount in decimal string format. + */ + amount: string(), + + /** + * Asset information. + */ + asset: AssetStruct, +}); + +/** + * This struct represents a participant in a transaction. + * + * @example + * ```ts + * from: [ + * { + * address: '0x1234...', + * amount: '0.01', + * asset: { + * id: 'eip155:1/slip44:60', + * unit: 'ETH', + * }, + * }, + * ], + * ``` + */ +const ParticipantStruct = object({ + /** + * Amount transferred from or to the participant. + */ + ...AmountStruct.schema, + + /** + * Participant address. + */ + address: string(), +}); + +/** + * This struct represents a blockchain transaction. + * + * @example + * ```ts + * { + * "id": "f5d8ee39a430901c91a5917b9f2dc19d6d1a0e9cea205b009ca73dd04470b9a6", + * "chain": "bip122:000000000019d6689c085ae165831e93", + * "account": "b9beb861-9761-4b97-89ce-d992be5f34da", + * "status": "confirmed", + * "timestamp": 1716367781, + * "type": "send", + * "from": [ + * { + * "address": "bc1qrp0yzgkf8rawkuvdlhnjfj2fnjwm0m8727kgah", + * "amount": "0.2001", + * "asset": { + * "id": "bip122:000000000019d6689c085ae165831e93/slip44:0", + * "unit": "BTC" + * } + * } + * ], + * "to": [ + * { + * "address": "bc1qrp0yzgkf8rawkuvdlhnjfj2fnjwm0m8727kgah", + * "amount": "0.1", + * "asset": { + * "id": "bip122:000000000019d6689c085ae165831e93/slip44:0", + * "unit": "BTC" + * } + * }, + * { + * "address": "bc1qrp0yzgkf8rawkuvdlhnjfj2fnjwm0m8727kgah", + * "amount": "0.1", + * "asset": { + * "id": "bip122:000000000019d6689c085ae165831e93/slip44:0", + * "unit": "BTC" + * } + * } + * ], + * "fee": { + * "amount": "0.0001", + * "asset": { + * "id": "bip122:000000000019d6689c085ae165831e93/slip44:0", + * "unit": "BTC" + * } + * } + * } + * ``` + */ +export const TransactionStruct = object({ + /** + * Chain-specific transaction ID. + */ + id: string(), + + /** + * Chain ID (CAIP-2). + */ + chain: string(), + + /** + * Account ID (UUIDv4). + */ + account: UuidStruct, + + /** + * Transaction status. + */ + status: enums(['pending', 'confirmed', 'failed']), + + /** + * Timestamp of when the transaction was added to the blockchain. + */ + timestamp: number(), + + /** + * Transaction type. This will be used by MetaMask to enrich the transaction + * details on the UI. + */ + type: enums([ + 'send', + 'receive', + 'call', + 'swap', + 'bridge', + 'stake', + 'unstake', + ]), + + /** + * Transaction sender addresses and amounts. + */ + from: array(ParticipantStruct), + + /** + * Transaction receiver addresses and amounts. + */ + to: array(ParticipantStruct), + + /** + * Transaction fee. + */ + fee: AmountStruct, +}); + +/** + * Transaction object. + * + * See {@link TransactionStruct}. + */ +export type Transaction = Infer;