Skip to main content
All CollectionsDevelopers Zone
Wallet API Reference
Wallet API Reference

Djuno Wallet API enables you to create wallets across a wide variety of chains using 3 different underlying signature schemes and curves.

Djuno Support avatar
Written by Djuno Support
Updated yesterday

APIs are exposed at a high level to view and transfer native cryptocurrencies, ERC20 tokens and ERC721 NFTs. Additionally we've exposed low-level transaction broadcast and raw signing APIs enabling integrations with hundreds of chains and ecosystems. All the Tier-1 chains listed below are fully indexed to provide accurate asset reporting and transaction history.

Wallets also support Delegated Signing, enabling a non-custodial configuration and an "Apple Pay for Crypto" UX via our WebAuthn/Passkeys integrations. If you have feedback on the Wallets API, please send it to [email protected].

Supported networks

You can use any of the follow enumerated types in the network field of Create Wallet:

Mainnets

Testnets

Tier

Standards

Finality*

Algorand

AlgorandTestnet

1

ASA

0

ArbitrumOne

ArbitrumSepolia

1

ERC-20, ERC-721

50

AvalancheC

AvalancheCFuji

1

ERC-20, ERC-721

0

Base

BaseSepolia

1

ERC-20, ERC-721

50

Bitcoin

BitcoinTestnet3

1

N/A

2

Bsc

BscTestnet

1

ERC-20, ERC-721

50

Cardano

CardanoPreprod

2

N/A

N/A

Ethereum

EthereumSepolia

1

ERC-20, ERC-721

12

FantomOpera

FantomTestnet

1

ERC-20, ERC-721

0

ICP (aka Dfinity)

No testnet support

1

ICRC(not generic)

1

Kaspa

No testnet support

1

N/A

20

Kusama

Westend

2

N/A

N/A

Litecoin

No testnet support

1

N/A

12

OGY (aka Origyn)

No testnet support

1

N/A

1

Optimism

OptimismSepolia

1

ERC-20, ERC-721

50

Polkadot

Westend

2

N/A

N/A

Polygon

PolygonAmoy

1

ERC-20, ERC-721

50

SeiPacific1

SeiAtlantic2

1

N/A

0

Solana

SolanaDevnet

1

SPL/SPL2022

0

Stellar

StellarTestnet

1

SEP-41/Classic

0

Tezos

TezosGhostnet

2

N/A

N/A

Ton

TonTestnet

1

TEP-74/Jetton

0

Tron

TronNile

1

TRC10/20/721

19

XrpLedger (aka Ripple)

XrpLedgerTestnet

2

N/A

N/A

Note: * Block Finality refers to the number of blocks that must be validated or mined after a transaction has been included in a block for that transaction to be considered irreversible. 0 indicates instant finality. Tier-2 chains are not indexed so finality doesn't apply. Tier-1 testnets report transactions immediately upon indexing.

Tier-1 vs Tier-2 support

We plan to add support for more blockchain networks over time. The supported features will vary depending on popularity and market demand.

Tier-1 blockchain networks will support all wallet features, including automatic detection of wallet asset and NFT balances if applicable, and on-chain asset transfer history. Tier-1 support also include transfer asset, broadcast transaction and generate signature. Tier-1 chains also support Webhooks driven by chain indexing.

Tier-2 blockchain networks do not track tokens or on-chain history. Only the balance of the native token, which is used to pay transaction fees, is returned. Tier-2 support includes Broadcast Transaction, Generate Signature, and Transfer Asset for native chain cryptocurrency only. Webhooks are not available for Tier-2 chains.

Pseudo Networks

We also support wallets not tied to a blockchain network. You can create an unbound wallet by setting the network field to one of the supported signature schemes, currently KeyECDSA, KeyECDSAStark, or KeyEdDSA. You can use these wallets for more advanced use cases, for example:

  • Use Dfns wallets with blockchains Dfns doesn't natively support, as long as they use either ECDSA, ECDSAStark or EdDSA.

  • Use Dfns wallets with private blockchains that Dfns have access to, such as Polygon Supernets or Avalanche Subnets.

  • Use the same Dfns wallets across multiple blockchain networks.

The unbound wallets only support Generate Signature. To help improve the developer experience with generate signature, our TypeScript SDK includes integrations with different blockchain SDKs, like ethers.js 5 and 6 or Solana web3.js. Browse through the included examples to see how to develop Dapps with Dfns wallets.

Create Wallet

POST /wallets

Creates new Wallet associated with the given chain (such as Ethereum or Polygon). Returns a new wallet entity.

Required Permissions

Name

Conditions

Wallets:Create*

Always Required

Wallets:Tags:Add

only required if tags are specified during wallet creation.

Request

Property

Type - Optional

Description

network*

String

Network used for the wallet (See Supported Networks + Pseudo Network for possible values)

name

String - Optional

Name given to the wallet

tags

String List - Optional

List of tags to be created for this wallet. If specified, requires the Wallets:Tags:Add permission, like the Tag Wallet endpoint.

delayDelegation

Boolean - Optional

Specify this if you want to create the wallet from a service account and later delegate it to an end user. Defaults to false.

delegateTo

String - Optional

ID of the end-user you wish to delegate this wallet to. This End User will then own this wallet, and the wallet will only be able to be used with an End-User's signature.

Example

{
"network": "EthereumSepolia",
"name": "my-wallet"
}

Response

The response body is the created Wallet. The Wallet object has those fields:

  • id - string - ID of the wallet

  • network - string - Network used for the wallet (See Supported Networks for possible values)

  • name - (Optional) string - Name given to the wallet

  • address - (Optional) string - Wallet address on its corresponding network. If using a Pseudo Network, this field will not be set.

  • status - string - Status of the wallet, can be one of Active, Archived.

  • signingKey - object - Info about the signing key corresponding to that wallet

    • scheme - string - Supported schemes are ECDSA or EdDSA

    • curve - string - Key curve. Can be ed25519 or secp256k1

    • publicKey - string - Hex-encoded value of public key

  • dateCreated - string - ISO 8601 date string when wallet was created

  • imported - (Optional) boolean - is true if the wallet is an imported wallet.

  • exported - (Optional) boolean - is true if the wallet was already exported at least once.

  • dateExported - (Optional) string - ISO 8601 date string when wallet was first exported.

  • tags - (Optional) string list - List of tags on that wallet

  • custodial - Boolean - Specifies whether the wallet is onwed by and EndUser (non-custodial), or by your organisation (custodial)

200 Response example

{
"id": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"status": "Active",
"name": "My awesome wallet",
"address": "0x00e3495cf6af59008f22ffaf32d4c92ac33dac47",
"dateCreated": "2023-04-14T20:41:28.715Z",
"signingKey": {
"curve": "secp256k1",
"scheme": "ECDSA",
"publicKey": "e2375c8c9e87bfcd0be8f29d76c818cabacd51584f72cb2222d49a13b036d84d3d"
}
}

Update Wallet

PUT /wallets/{walletId}

Updates the name or externalID of an existing Wallet.

Required Permissions

Name

Conditions

Wallets:Update*

Always Required

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Request

Property

Type - Optional

Description

name

String - Optional

Name given to the wallet

externalid

String - Optional

External id usually used as a foreign key to an external database.

Example

{
"name": "my-wallet-updated"
}

Response

200 Response example

{
"id": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"status": "Active",
"name": "My awesome wallet",
"address": "0x00e3495cf6af59008f22ffaf32d4c92ac33dac47",
"dateCreated": "2023-04-14T20:41:28.715Z",
"signingKey": {
"curve": "secp256k1",
"scheme": "ECDSA",
"publicKey": "e2375c8c9e87bfcd0be8f29d76c818cabacd51584f72cb2222d49a13b036d84d3d"
}
}

Delegate Wallet

POST /wallets/:walletId/delegate

Only wallets created with "delayDelegation: true" can then be delegated to an end-user. It means you need to know ahead of time that you're creating a wallet meant to be delegated to an end-user later. This is a safety to prevent, for example, a treasury wallet from being unintentionally delegated to an end-user.

This operation is irreversible. The wallet ownership will be transferred to the end-user

In most cases, when you want to implement Delegated Signing, simply have the end-user create the wallet, in which case it will the noncustodial from the start. There are some rare cases, however, where the wallet must be created before the user has accessed the system. To accommodate this, we've added the ability to create a wallet from a service account, and then later delegate it (ie. transfer ownership of it) to an end user via this endpoint.

Required Permissions

Name

Conditions

Wallets:Delegate

Always Required

Request

Request body fields

Required/Optional

Description

Type

userId

Required

The ID of the end-user to delegate the wallet to. Eg: "us-gk0i1-5bvju-lj2h98s9h9r5tqp1"

String

Example

{
"userId": "us-gk0i1-5bvju-lj2h98s9h9r5tqp1"
}

Response

The response indicates the status of the operation.

200 Response example

{
"status": "Delegated"
}

Get Wallet by ID

GET /wallets/{walletId}

Retrieves a Wallet by its ID.

Required Permissions

Name

Conditions

Wallets:Read

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Response

The response body is the Wallet. The Wallet object has those fields:

  • id - string - ID of the wallet

  • network - string - Network used for the wallet (See Supported Networks for possible values)

  • name - (Optional) string - Name given to the wallet

  • address - (Optional) string - Wallet address on its corresponding network. If using a Pseudo Network, this field will not be set.

  • status - string - Status of the wallet, can be one of Active, Archived.

  • signingKey - object - Info about the signing key corresponding to that wallet

    • scheme - string - Supported schemes are ECDSA or EdDSA

    • curve - string - Key curve. Can be ed25519 or secp256k1

    • publicKey - string - Hex-encoded value of public key

  • dateCreated - string - ISO 8601 date string when wallet was created

  • imported - (Optional) boolean - is true if the wallet is an imported wallet.

  • exported - (Optional) boolean - is true if the wallet was already exported at least once.

  • dateExported - (Optional) string - ISO 8601 date string when wallet was first exported.

200 Response example

{
"id": "pk-september-sad-3...18",
"network": "EthereumGoerli",
"status": "Active",
"signingKey": {
"scheme": "ECDSA",
"curve": "secp256k1",
"publicKey": "03e849e03fa8b962...cc6e3"
},
"address": "0xf42d9f717e0223a70ae195d1d31b798dc8a8b1d2",
"dateCreated": "2021-01-01T00:00:00.000Z",
"custodial": true,
"tags": []
}

List Wallets

GET /wallets/?ownerId={userId}&paginationToken={token}

Retrieves a list of wallets.

Required Permissions

Name

Conditions

Wallets:Read

Always Required

Parameters

Query parameters

Query string parameter

Required/Optional

Description

Type

ownerId

Optional

Filters the wallets returned to the userId of the owner of the wallets. Can be used to get all wallets belonging to a specific end user.

String

ownerUsername

Optional

Filters the wallets returned to the username of the owner of the wallets. Can be used to get all wallets belonging to a specific end user.

String

limit

Optional

Maximum number of items to return. Default to 50.

Number

paginationToken

Optional

Opaque token used to retrieve the next page. Returned as nextPageToken from the previous request.

String

Response

200 Response example

{
"items": [
{
"id": "pk-september-sad-3...18",
"network": "EthereumGoerli",
"status": "Active",
"signingKey": {
"scheme": "ECDSA",
"curve": "secp256k1",
"publicKey": "03e849e03fa8b962...cc6e3"
},
"address": "0xf42d9f717e0223a70ae195d1d31b798dc8a8b1d2",
"dateCreated": "2021-01-01T00:00:00.000Z",
"custodial": true,
"tags": []
},
...
],
"nextPageToken": "WszQXoENUIYyoBQjJm4DE6QhCk2sB7WAh9kykUMaTQcD25SToKbuXkgf3td8ZYb2LrtopPLo35u407gwwA1Sug=="
}

Get Wallet Assets

GET /wallets/{walletId}/assets

Retrieves a list of assets owned by the specified Wallet. Note return values vary by chain as shown below.

Required Permissions

Name

Conditions

Wallets:Read

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Response (EVM)

200 Response example

verified contracts have been certified authentic by CoinMarketCap.

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Ethereum",
"assets": [
{
"symbol": "ETH",
"decimals": 18,
"balance": "1000000000000000000",
"verified": true
},
{
"contract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"name": "USD Coin",
"symbol": "USDC",
"decimals": 6,
"balance": "100000000000000000000",
"verified": true
},
{
"contract": "0x514910771af9ca656af840dff83e8264ecf986ca",
"name": "Chainlink Token",
"symbol": "LINK",
"decimals": 18,
"balance": "20000000000000000000",
"verified": true
}
]
}

Algorand

Algorand Standard Assets

Get Algorand standard assets, or ASAs.

200 response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Algorand",
"assets": [
{
"kind": "Asa",
"assetId": "xxxxxxxxx",
"symbol": "USDC",
"decimals": 6,
"verified": true,
"balance": "200000000"
},
...
}

Solana

Solana Program Library Token (SPL)

200 response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Solana",
"assets": [
{
"kind": "Spl",
"mint": "4zMMC9srt5RixxxxxxxxxxxxxEERYPJgZJDncDU",
"symbol": "USDC",
"decimals": 6,
"balance": "10000000"
},
...
}

Solana Program Library Token 2022 (SPL-2022)

200 response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Solana",
"assets": [
{
"kind": "Spl2022",
"mint": "DnECowYZoUEyqfxxxxxxxxxxxxx5v4iyToZxFjDZ",
"symbol": "Dfns22",
"decimals": 8,
"balance": "99999999999"
},
...
}

Stellar

Classic Stellar Assets (SEP-41)

Get classic Stellar Assets. They all implement the SEP-41 token interface.

200 response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Stellar",
"assets": [
{
"kind": "Sep41",
"mint": "GBBD47IF6LWK7P7xxxxxxxxxxxxT4AQH3ZLLFLA5",
"symbol": "USDC",
"decimals": 8,
"balance": "99999999999"
},
...
}

TON

TON TEP74 Jetton

Get Jetton.

200 response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Ton",
"assets": [
{
"kind": "Tep74",
"mint": "kQBFAGo2Af6xxxxxxxxxxxW_cWLyFz",
"symbol": "Dfns",
"decimals": 9,
"balance": "99999999999999"
},
...
}

TRON

TRC-10

Get TRON's TRC-10 fungible tokens

200 response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Tron",
"assets": [
{
"kind": "Trc10",
"tokenId": "1005273",
"symbol": "DFNS",
"decimals": 6,
"balance": "10000000997"
},
...
}

TRC-20

Get fungible tokens that implement the TRC-20 smart contract specification.

200 response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Tron",
"assets": [
{
"kind": "Trc20",
"contract": "TXLAQ63XgxxxxxxxxxxEmLMEqcdj",
"symbol": "USDT",
"decimals": 6,
"balance": "99999000000"
},
...
}

Get Wallet NFTs

GET /wallets/{walletId}/nfts

Retrieves a list of NFTs owned by the specified Wallet.

Required Permissions

Name

Conditions

Wallets:Read

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Response

200 Response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Ethereum",
"nfts": [
{
"kind": "Erc721",
"contract": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
"symbol": "BAYC",
"tokenId": "8500",
"tokenUri": "ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/8500"
},
{
"kind": "Erc721",
"contract": "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
"symbol": "BAYC",
"tokenId": "2944",
"tokenUri": "ipfs://QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/2944"
}
]
}

Get Wallet History

GET /wallets/{walletId}/history?paginationToken={token}

Retrieves a list of historical on chain activities for the specified wallet.

Required Permissions

Name

Conditions

Wallets:Read

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Query parameters

Query string parameter

Required/Optional

Description

Type

limit

Optional

Maximum number of items to return. Default to 50.

Number

paginationToken

Optional

Opaque token used to retrieve the next page. Returned as nextPageToken from the previous request.

String

Response

{
"items": [
{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "Ethereum",
"kind": "Erc20Transfer",
"direction": "Out",
"blockNumber": 19036906,
"timestamp": "2024-01-18T23:03:59.000Z",
"txHash": "0x8e88793607610a83798eb5ec6dde861f3e459c7e4a22e78b0d2e675b86d0d1e7",
"index": "134",
"contract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"from": "0xea09cf8a006493566f8a8fd3d0b32ebff5939d6a",
"to": "0xc42754e6f79f15082613b2b4ebead83dcf8116b6",
"value": "1000000",
"fee": "1542993669053672",
"metadata": {
"asset": {
"symbol": "USDC",
"decimals": 6,
"verified": true
},
"fee": {
"symbol": "ETH",
"decimals": 18,
"verified": true
}
}
},
...
],
"nextPageToken": "WszQXoENUIYyoBQjJm4DE6QhCk2sB7WAh9kykUMaTQcD25SToKbuXkgf3td8ZYb2LrtopPLo35u407gwwA1Sug=="
}

Tag Wallet

PUT /wallets/{walletId}/tags

Tags are a way to add arbitrary metadata to wallets which can be used to filter them in policy engine. For example, you may want to create deposit wallets which are whitelisted to only send to an omnibus account. In this case, you could add a tag "deposit" to each new wallet and then filter a whitelisting policy to just those wallets.

Required Permissions

Name

Conditions

Wallets:Tags:Add

Always Required

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Request body

Property

Type

Description

tags*

String List

The tags to apply to the wallet

{
"tags": ["deposit", "customer:xyz", "security/critical"]
}

200 Response

{}

Untag Wallet

DELETE /wallets/{walletId}/tags

Removes the specified tags from a wallet.

Required Permissions

Name

Conditions

Wallets:Tags:Delete

Always Required

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Request body

Property

Type

Description

tags*

List of String

The tags to remove from the wallet

{
"tags": ["DepositWallet"]
}

200 Response

{}

Transfer Asset from Wallet

POST /wallets/{walletId}/transfers

Transfer an asset out of the specified wallet to a destination address. For all fungible token transfers, the transfer amount must be specified in the minimum denomination of that token. For example, use the amount in Satoshi for a Bitcoin transfer, or the amount in Wei for an Ethereum transfer etc.

Required Permissions

Name

Conditions

Wallets:TransferAsset

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Native Token

Transfer the native token of the network. All networks support the native token type.

Request body

Property

Type

Description

kind*

String

Native

to*

String

The destination address

amount*

String

The amount of native tokens to transfer in minimum denomination

priority

(Optional) String

The priority that determines the fees paid for the transfer [1]

memo

(Optional) String

The memo or destination tag [2]

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

  1. All EVM compatible networks and Bitcoin support priority. Not supported for other networks. The accepted values are Slow, Standard and Fast. When specified, it uses the estimate fees API to calculate the transfer fees. When not specified, the transfer will use the fees returned from the blockchain node providers.

  2. Stellar and XrpLedger support memo. Not valid for other networks.

Sample request body

{
"kind": "Native",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"amount": "1000000000"
}

200 response example

{
"id": "xfr-1vs8g-c1ub1-xxxxxxxxxxxxxxxx",
"walletId": "wa-39abb-e9kpk-xxxxxxxxxxxxxxxx",
"network": "Ethereum",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Native",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"amount": "1000000000"
},
"metadata": {
"asset": {
"symbol": "ETH",
"decimals": 18,
"verified": true,
"quotes": {
"EUR": 2802.867647101728,
"USD": 3020.82462287215
}
}
},
"dateRequested": "2023-05-08T19:14:25.568Z",
"status": "Pending"
}

Algorand

Algorand Standard Assets

Transfer Algorand standard assets, or ASAs.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Asa

String

assetId

Required

The asset ID of the token

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

Sample request body

{
"kind": "Asa",
"assetId": "31566704",
"to": "FRZP423Y7MNMTG4OOLESESTPCFGGHZMY7QN462YEQAJK5H6EOMFHZG73UA",
"amount": "1000000"
}

200 response example

{
"id": "xfr-22e36-7p55v-xxxxxxxxxxxxxxxx",
"walletId": "wa-39abb-e9kpk-xxxxxxxxxxxxxxxx",
"network": "Algorand",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Asa",
"assetId": "31566704",
"to": "FRZP423Y7MNMTG4OOLESESTPCFGGHZMY7QN462YEQAJK5H6EOMFHZG73UA",
"amount": "1000000"
},
"metadata": {
"asset": {
"symbol": "USDC",
"decimals": 6,
"verified": true
}
},
"dateRequested": "2024-05-10T14:35:55.768Z",
"status": "Pending"
}

EVM Compatible Networks

ERC-20

Transfer fungible tokens that implement the ERC-20 specification.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Erc20

String

contract

Required

The ERC20 contract address

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

priority

Optional

The priority that determines the fees paid for the transfer

String

Sample request body

{
"kind": "Erc20",
"contract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"amount": "1000000"
}

200 response example

{
"id": "xfr-6ulmv-sa183-xxxxxxxxxxxxxxxx",
"walletId": "wa-40f4f-51gpm-xxxxxxxxxxxxxxxx",
"network": "Ethereum",
"requester": {
"userId": "us-4vu4v-kud3l-xxxxxxxxxxxxxxxx",
"appId": "ap-7c2pm-avfsr-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Erc20",
"contract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"amount": "1000000",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f"
},
"metadata": {
"asset": {
"symbol": "USDC",
"decimals": 6,
"verified": true,
"quotes": {
"USD": 1.000804849917271,
"EUR": 0.9201529894769885
}
}
},
"status": "Confirmed",
"fee": "1542993669053672",
"txHash": "0x8e88793607610a83798eb5ec6dde861f3e459c7e4a22e78b0d2e675b86d0d1e7",
"dateRequested": "2024-01-18T23:03:53.739Z",
"dateBroadcasted": "2024-01-18T23:03:55.685Z",
"dateConfirmed": "2024-01-18T23:03:59.000Z"
}

ERC-721

Transfer non-fungible tokens that implement the ERC-721 specification

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Erc721

String

contract

Required

The ERC721 contract address

String

to

Required

The destination address

String

tokenId

Required

The token to transfer

String

priority

Optional

The priority that determines the fees paid for the transfer

String

Sample request body

{
"kind": "Erc721",
"contract": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"tokenId": "1"
}

200 response example

{
"id": "xfr-4n0dm-fqju5-xxxxxxxxxxxxxxxx",
"walletId": "wa-39abb-e9kpk-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Erc721",
"contract": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"tokenId": "1"
},
"dateRequested": "2023-05-08T18:10:43.521Z",
"status": "Pending"
}

Solana

Solana Program Library Token (SPL)

Transfer SPL tokens.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Spl

String

mint

Required

The mint account address

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

createDestinationAccount

Optional

If True, pay to create the associated token account of the recipient if it doesn't exist. Defaults to False.

Boolean

Sample request body

{
"kind": "Spl",
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"to": "3U6stgsD1FmA7o3omUguritCU8iWmUM7Rs6KqAHHxHVZ",
"amount": "1000000"
}

200 response example

{
"id": "xfr-4qc73-2kr4s-xxxxxxxxxxxxxxxx",
"walletId": "wa-3i0nv-fa4e7-xxxxxxxxxxxxxxxx",
"network": "Solana",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Spl",
"mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"to": "3U6stgsD1FmA7o3omUguritCU8iWmUM7Rs6KqAHHxHVZ",
"amount": "1000000"
},
"metadata": {
"asset": {
"symbol": "USDC",
"decimals": 6,
"verified": true
}
},
"dateRequested": "2024-06-11T13:46:55.175Z",
"status": "Pending"
}

Solana Program Library Token 2022 (SPL-2022)

Transfer SPL 2022 tokens.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Spl2022

String

mint

Required

The mint account address

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

createDestinationAccount

Optional

If True, pay to create the associated token account of the recipient if it doesn't exist. Defaults to False.

Boolean

Sample request body

{
"kind": "Spl2022",
"mint": "DnECowYZoUEyqfntQmeLPPH5s1TLR7P5v4iyToZxFjDZ",
"to": "3U6stgsD1FmA7o3omUguritCU8iWmUM7Rs6KqAHHxHVZ",
"amount": "1000000"
}

200 response example

{
"id": "xfr-2kmot-fk31j-xxxxxxxxxxxxxxxx",
"walletId": "wa-3i0nv-fa4e7-xxxxxxxxxxxxxxxx",
"network": "Solana",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Spl2022",
"mint": "DnECowYZoUEyqfntQmeLPPH5s1TLR7P5v4iyToZxFjDZ",
"to": "3U6stgsD1FmA7o3omUguritCU8iWmUM7Rs6KqAHHxHVZ",
"amount": "1000000"
},
"metadata": {
"asset": {
"symbol": "Dfns22",
"decimals": 8
}
},
"dateRequested": "2024-06-05T17:02:43.295Z",
"status": "Pending"
}

Stellar

Classic Stellar Assets (SEP-41)

Transfer classic Stellar Assets. They all implement the SEP-41 token interface.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Sep41

String

issuer

Required

The asset issuer address

String

assetCode

Required

The asset code

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

memo

Optional

The memo

String

Sample request body

{
"kind": "Sep41",
"issuer": "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
"assetCode": "USDC",
"to": "GAZWLHTNAOJWW52GZCUJAS5MSXK7LAWCUC5TFOFFVDQ7CDTNFODJ37GB",
"amount": "1000000"
}

200 response example

{
"id": "xfr-gbasv-hssu9-xxxxxxxxxxxxxxxx",
"walletId": "wa-46sdf-a9stj-xxxxxxxxxxxxxxxx",
"network": "Stellar",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Sep41",
"issuer": "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN",
"assetCode": "USDC",
"to": "GAZWLHTNAOJWW52GZCUJAS5MSXK7LAWCUC5TFOFFVDQ7CDTNFODJ37GB",
"amount": "1000000"
},
"metadata": {
"asset": {
"symbol": "USDC",
"decimals": 7,
"verified": true
}
},
"dateRequested": "2024-05-08T14:34:04.446Z",
"status": "Pending"
}

TON

TON TEP74 Jetton

Transfer Jetton.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Tep74

String

master

Required

The jetton master address

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

Sample request body

{
"kind": "Tep74",
"master": "EQAIZUJZxUgjovq8C6P5tRGwSsydiCtKiwRnycPnN1k4WpFo",
"to": "EQBfYLuQwjbBd-LAZ6eNC26XmVVxEl86MQPKG981hdTSicL_",
"amount": "1000000"
}

200 response example

{
"id": "xfr-4qc73-2kr4s-xxxxxxxxxxxxxxxx",
"walletId": "wa-3i0nv-fa4e7-xxxxxxxxxxxxxxxx",
"network": "Solana",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Tep74",
"master": "EQAIZUJZxUgjovq8C6P5tRGwSsydiCtKiwRnycPnN1k4WpFo",
"to": "EQBfYLuQwjbBd-LAZ6eNC26XmVVxEl86MQPKG981hdTSicL_",
"amount": "1000000"
}
"metadata": {
"asset": {
"symbol": "jUSDC",
"decimals": 6,
"verified": true
}
},
"dateRequested": "2024-06-11T13:46:55.175Z",
"status": "Pending"
}

TRON

TRC-10

Transfer TRON's TRC-10 fungible tokens

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Trc10

String

tokenId

Required

The token ID

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

Sample request body

{
"kind": "Trc10",
"tokenId": "1005273",
"to": "TADDx31pdCFfp3XrYxp6fQGbRxriYFLTrx",
"amount": "10000"
}

TRC-20

Transfer fungible tokens that implement the TRC-20 smart contract specification.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Trc20

String

contract

Required

The smart contract address

String

to

Required

The destination address

String

amount

Required

The amount of tokens to transfer in minimum denomination

String

Sample request body

{
"kind": "Trc20",
"contract": "TXLAQ63Xg1NAzckPwKHvzw7CSEmLMEqcdj",
"to": "TQJNezrbfJ3akrGgR7eM2fWyFpsKeM8wzN",
"amount": "1000000"
}

TRC-721

Transfer non-fungible tokens that implement the TRC-721 smart contract specification.

Request body

Request body fields

Required/Optional

Description

Type

kind

Required

Trc721

String

contract

Required

The smart contract address

String

to

Required

The destination address

String

tokenId

Required

The token to transfer

String

Sample request body

{
"kind": "Trc721",
"contract": "TKgnDMWHYmwH24REe9XnrnwcNCvtb53n8Q",
"to": "TQJNezrbfJ3akrGgR7eM2fWyFpsKeM8wzN",
"tokenId": "1"
}

Response Statuses

Status

Definition

Pending

The request is pending approval due to a policy applied to the wallet

Executing

The request is approved and is in the process of being executed (note this status is only set for a short time between pending and broadcasted)

Broadcasted

The transaction has been successfully written to the mempool

Confirmed

The transaction has been confirmed on-chain by our indexing pipeline

Failed

Indicates a system failure to complete the request

Rejected

The request has been rejected by a policy approval action

Get Wallet Transfer Request by ID

GET /wallets/{walletId}/transfers/{transferId}

Retrieves a Wallet Transfer Request by its ID.

Required Permissions

Name

Conditions

Wallets:ReadTransfer

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-39abb-e9kpk-xxxxxxxxxxxxxxxx

transferId

Unique identifier of the transfer request. ex. tf-2mq6c-iu1es-xxxxxxxxxxxxxxxx

Response

200 Response example

{
"id": "xfr-2mq6c-iu1es-xxxxxxxxxxxxxxxx",
"walletId": "wa-39abb-e9kpk-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Erc20",
"contract": "0x779877a7b0d9e8603169ddbd7836e478b4624789",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"amount": "1000000000"
},
"status": "Confirmed",
"txHash": "0x177bdb7ac9e417a45b0b5c68317d1723bb4f2b0acc57f87e3e3fdc0e50d32a0f",
"fee": "77433000412976",
"dateRequested": "2023-05-08T17:30:52.882Z",
"dateBroadcasted": "2023-05-08T17:30:59.815Z",
"dateConfirmed": "2023-05-08T17:31:12.000Z",
"approvalId": "ap-...", // defined only if an approval process was triggered as the result of a policy ("status" will be "Pending" then)
}

List Wallet Transfer Requests

GET /wallets/{walletId}/transfers?paginationToken={token}

Retrieves a list of transfer requests for the specified wallet.

Required Permissions

Name

Conditions

Wallets:ReadTransfer

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-39abb-e9kpk-xxxxxxxxxxxxxxxx

Query parameters

Query string parameter

Required/Optional

Description

Type

limit

Optional

Maximum number of items to return. Default to 50.

Number

paginationToken

Optional

Opaque token used to retrieve the next page. Returned as nextPageToken from the previous request.

String

Response

200 Response example

{
"walletId": "wa-39abb-e9kpk-xxxxxxxxxxxxxxxx",
"items": [
{
"id": "xfr-61bai-v6lao-xxxxxxxxxxxxxxxx",
"walletId": "wa-39abb-e9kpk-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Native",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"amount": "1000000000"
},
"status": "Confirmed",
"txHash": "0x4c94e7335efdb9a708f143b0f50f0130cff07271215042050bdd8ad429fa146f",
"fee": "31500000147000",
"dateRequested": "2023-05-09T22:39:33.198Z",
"dateBroadcasted": "2023-05-09T22:39:38.815Z",
"dateConfirmed": "2023-05-09T22:39:48.000Z"
},
{
"id": "xfr-4n0dm-fqju5-xxxxxxxxxxxxxxxx",
"walletId": "wa-39abb-e9kpk-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Erc721",
"contract": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"tokenId": "1"
},
"status": "Confirmed",
"txHash": "0xcddf1167b53fcbe61c5360b50a2a075173049970c4c9dbea1e45db5ff9e41c15",
"fee": "95866500447377",
"dateRequested": "2023-05-08T18:10:43.521Z",
"dateBroadcasted": "2023-05-08T18:10:48.373Z",
"dateConfirmed": "2023-05-08T18:11:00.000Z"
},
...
],
"nextPageToken": "WszQXoENUIYyoBQjJm4DE6QhCk2sB7WAh9kykUMaTQcD25SToKbuXkgf3td8ZYb2LrtopPLo35u407gwwA1Sug=="
}

Sign and Broadcast Transaction from Wallet

POST /wallets/{walletId}/transactions

Sign & Broadcast transaction enables communication with any arbitrary smart contract by replicating the native transaction protocol fields in the body of the request. It executes a signature, constructs the transaction for the target chain, and then broadcasts the transaction. It can be used to make native payments, call smart contract functions, and even deploy new smart contracts. Note for reading from a "view" function on EVM chains, please use Call Read Function.

Required Permissions

Name

Conditions

Wallets:BroadcastTransaction

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Request Body

The body of the request will depend on the chain you are targeting. Please find the chain in question by expanding this section in the left hand navigation:

Response Statuses

Status

Definition

Pending

The request is pending approval due to a policy applied to the wallet

Executing

The request is approved and is in the process of being executed (note this status is only set for a short time between pending and broadcasted)

Broadcasted

The transaction has been successfully written to the mempool

Confirmed

The transaction has been confirmed on-chain by our indexing pipeline

Failed

Indicates a system failure to complete the request

Rejected

The request has been rejected by a policy approval action

Algorand: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Algorand, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x81a374786e89a3616d74cd2710a3666565cd03e8a26676ce02340f13a367656eac746573746e65742d76312e30a26768c4204863b518a4b3c84ec810f22d4f1081cb0f71f059a7ac20dec62f7f70e5093a22a26c76ce023412fba3726376c4201256a859b39429ee178e0a65056fb33d51c5139044f6a2603c144278010c7684a3736e64c4201256a859b39429ee178e0a65056fb33d51c5139044f6a2603c144278010c7684a474797065a3706179"
}

200 response example

{
"id": "tx-2bbd9-7dvdf-xxxxxxxxxxxxxxxx",
"walletId": "wa-341e6-12nj6-xxxxxxxxxxxxxxxx",
"network": "AlgorandTestnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x81a374786e89a3616d74cd2710a3666565cd03e8a26676ce02340f13a367656eac746573746e65742d76312e30a26768c4204863b518a4b3c84ec810f22d4f1081cb0f71f059a7ac20dec62f7f70e5093a22a26c76ce023412fba3726376c4201256a859b39429ee178e0a65056fb33d51c5139044f6a2603c144278010c7684a3736e64c4201256a859b39429ee178e0a65056fb33d51c5139044f6a2603c144278010c7684a474797065a3706179"
},
"status": "Broadcasted",
"txHash": "RYMBSTJPYM5KTADZ3GHOSHMTEH5DHEWEFKNG6PWPMT44GHLSUDDA",
"dateRequested": "2024-02-08T20:19:38.428Z",
"dateBroadcasted": "2024-02-08T20:19:38.990Z"
}

Typescript Example with AlgoSDK

First install the AlgoSDK. You can find the full documentation here: https://github.com/algorand/js-algorand-sdk

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import { Algodv2, encodeObj, makePaymentTxnWithSuggestedParamsFromObject } from 'algosdk'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const algod = new Algodv2(ALGORAND_TOKEN, ALGORAND_NODE_URL)

const suggestedParams = await algod.getTransactionParams().do()
const transaction = makePaymentTxnWithSuggestedParamsFromObject({
from: wallet.address,
suggestedParams,
to: 'CJLKQWNTSQU64F4OBJSQK35THVI4KE4QIT3KEYB4CRBHQAIMO2CD6JWBCY',
amount: 10000,
})

const bytes = encodeObj({ txn: transaction.get_obj_for_encoding() })

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${Buffer.from(bytes).toString('hex')}`,
},
})

Bitcoin/Litecoin: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Bitcoin, always Psbt

transaction*

Hex String

The hex encoded PSBT as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Psbt",
"psbt": "0x70736274ff0100710200000001ca17431a33a13d3ef8bfb041c8546071f9d3a609abe3c91efbed83265e1426730100000000ffffffff02e803000000000000160014a40a65b46ff36c53f1afb8e35e25a4c0bcfc9979d6d1150000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000000001011f54d6150000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000"
}

200 response example

{
"id": "tx-2jfp6-db4jc-xxxxxxxxxxxxxxxx",
"walletId": "wa-36a0p-pdil7-xxxxxxxxxxxxxxxx",
"network": "BitcoinTestnet3",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Psbt",
"psbt": "0x70736274ff0100710200000001ca17431a33a13d3ef8bfb041c8546071f9d3a609abe3c91efbed83265e1426730100000000ffffffff02e803000000000000160014a40a65b46ff36c53f1afb8e35e25a4c0bcfc9979d6d1150000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000000001011f54d6150000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000"
},
"status": "Broadcasted",
"txHash": "97ad64f69168eb4ffd2b2f6756f1651eff43bcca04695b3cea834eebff5b7524",
"dateRequested": "2024-01-10T19:40:07.022Z",
"dateBroadcasted": "2024-01-10T19:40:07.277Z"
}

Typescript Example with BitcoinJS

First install the BitcoinJS SDK. You can find the full documentation here: https://github.com/bitcoinjs/bitcoinjs-lib

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import { networks, payments, Psbt } from 'bitcoinjs-lib'
import axios from 'axios'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })
const publicKey = Buffer.from(wallet.signingKey.publicKey, 'hex')

const network = networks.testnet
const { address } = payments.p2wpkh({
pubkey: publicKey,
network,
})

const txid = '87872516c6e93f136fc6c493c7172596b11c695e27889de7532abffcac2a4b5e'
const n = 1
const utxo = (
await axios.post(BITCOIN_NODE_URL, {
jsonrpc: '2.0',
id: 'gettxout',
method: 'gettxout',
params: [txid, n, false],
})
).data.result

const balance = utxo.balance * 100000000
const amount = 1
const fee = 150

const psbt = new Psbt({ network })
psbt.addInput({
hash: txid,
index: n,
witnessUtxo: {
script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
value: balance,
},
})

psbt.addOutput({
address: 'tb1q5s9xtdr07dk98ud0hr34ufdycz70exte2kehm2',
value: amount,
})

psbt.addOutput({
address,
value: balance - amount - fee,
})

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: { kind: 'Psbt', psbt: `0x${psbt.toHex()}` },
})

Cardano: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Cardano, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x84a3008182582082544414292ededfa716ae42af007ecff823c58796cb9ba60330699fb4d55d7901018282581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621a000cf4ae82581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621b0000000253db20cd021a00028785a0f5f6"
}

200 response example

{
"id": "tx-65s39-hsdh3-xxxxxxxxxxxxxxxx",
"walletId": "wa-7nej2-e3o6d-xxxxxxxxxxxxxxxx",
"network": "CardanoPreprod",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x84a3008182582082544414292ededfa716ae42af007ecff823c58796cb9ba60330699fb4d55d7901018282581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621a000cf4ae82581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621b0000000253db20cd021a00028785a0f5f6"
},
"status": "Broadcasted",
"txHash": "2139a2a4f70aa01a4864308579bbdb769b6669b6b39419618b871d3aed3a82e6",
"dateRequested": "2024-05-09T16:21:36.949Z",
"dateBroadcasted": "2024-05-09T16:21:37.809Z"
}

Typescript Example with MeshJS SDK

First install the MeshJS SDK. You can find the full documentation here: https://docs.meshjs.dev/

You also need a service that tracks the account's UTXO, for example Blockfrost. The Dfns TypeScript SDK has an example demonstrating how to write a custom Blockfrost initiator plugin for MeshJS.

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import { BlockfrostProvider, Transaction } from '@meshsdk/core'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const provider = new BlockfrostProvider(process.env.BLOCKFROST_PROJECT_ID!)
const initiator = new CustomInitiator(wallet.address, provider)

const transaction = await new Transaction({ initiator })
.sendLovelace('addr_test1vq5eele9enryyqkg4wrjyp7x4gpshvkr6rylkwtyau56g3qgrcks9', '1000000')
.build()

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${transaction}`,
},
})

EVM: Broadcast Transaction

EVM chains like Ethereum, Polygon, BSC, Arbitrum, etc support the use of templates to broadcast transactions. Select the following based on the template kind:

  • Evm: Use this template if you don't want to worry about gas parameters.

  • Eip1559: Use this template to interact with chains that support the new EIP-1559 gas standard (most chains do now).

  • Transaction: Use this template to just pass in the fully serialized EVM transaction (formatted and encoded using eg Ethersjs library)

EVM Template

Request fields

Required - Type

Description

kind*

Required - String

Evm

to*

Required - String

Blockchain address of target contract or payee.

value

(Optional. Required only if making a payment) - String (representing a integer eg "1000000")

Amount of the native currency to transfer denominated in WEI.

data

(Optional) String

Encoded hex string indicating which function in the smart contract to call with which parameters. Can also be an entire encoded contract in the case of contract deployment.

nonce

(Optional) Integer

The transaction number to guarantee idempotency. If omitted, it will be provided automatically. Note the same nonce can be submitted multiple times with a higher maxFeePerGas to "overwrite" existing transactions in the mempool.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Evm",
"to": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"data": "0x40d097c3000000000000000000000000d2f77f85a50cdd650ca562f3a180284e1d5b4934",
}

200 response example

{
"id": "tx-hpq5n-4p9s9-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Evm",
"to": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"data": "0x40d097c3000000000000000000000000d2f77f85a50cdd650ca562f3a180284e1d5b4934"
},
"status": "Broadcasted",
"txHash": "0x86b092a7fde26cca7fa49350d6d9244fb1f772d30c15aed48decea11fa68531f",
"dateRequested": "2023-05-08T19:27:04.680Z",
"dateBroadcasted": "2024-01-10T21:19:58.225Z"
}

EIP-1559 Template

Use this template to adjust the maxFeePerGas and maxPriorityFeePerGas of an EIP-1559 type-2 transaction. Keep in mind that not all EVM compatible chains support this standard.

Property

Required - Type

Description

kind*

String

Eip1559

to*

String

Blockchain address of target contract or payee.

value

(Optional - Required if making a payment) - String (representing an integer eg "1000000")

Amount of the native currency to transfer denominated in WEI.

data

(Optional) String

Encoded hex string indicating which function in the smart contract to call with which parameters. Can also be an entire encoded contract in the case of contract deployment.

nonce

(Optional) Integer

The transaction number to guarantee idempotency. If omitted, it will be provided automatically. Note the same nonce can be submitted multiple times with a higher maxFeePerGas to "overwrite" existing transactions in the mempool.

gasLimit

(Optional) String (representing an Integer)

The maximum amount of gas that can be spent for executing the transaction. If omitted, it will be calculated automatically.

maxPriorityFeePerGas

(Optional) String (representing an Integer)

The maximum amount of gas to be included as a tip to the validator. If omitted, it will be calculated automatically.

maxFeePerGas

(Optional) String (representing an Integer)

The maximum amount for gas willing to be paid for the transaction. If omitted, it will be calculated automatically.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Eip1559",
"to": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"data": "0x40d097c3000000000000000000000000d2f77f85a50cdd650ca562f3a180284e1d5b4934",
"maxFeePerGas": "1626000000000",
"maxPriorityFeePerGas": "1332000000000"
}

200 response example

{
"id": "tx-hpq5n-4p9s9-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Eip1559",
"to": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"data": "0x40d097c3000000000000000000000000d2f77f85a50cdd650ca562f3a180284e1d5b4934",
"maxFeePerGas": "1626000000000",
"maxPriorityFeePerGas": "1332000000000"
},
"status": "Broadcasted",
"txHash": "0x86b092a7fde26cca7fa49350d6d9244fb1f772d30c15aed48decea11fa68531f",
"dateRequested": "2023-05-08T19:27:04.680Z",
"dateBroadcasted": "2024-01-10T21:19:58.225Z"
}

Raw Transaction

You can also format the transaction using Ethers JS and the Dfns SDK:

Property

Type

Description

kind*

String

Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x02e783aa36a71503850d40e49def82520894e5a2ebc128e262ab1e3bd02bffbe16911adfbffb0180c0"
}

200 Response Example

{
"id": "tx-3p6n9-tdrn2-xxxxxxxxxxxxxxxx",
"walletId": "wa-19lns-o74qn-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x02e783aa36a71503850d40e49def82520894e5a2ebc128e262ab1e3bd02bffbe16911adfbffb0180c0"
},
"status": "Broadcasted",
"txHash": "0x86b092a7fde26cca7fa49350d6d9244fb1f772d30c15aed48decea11fa68531f",
"dateRequested": "2024-01-10T19:02:11.615Z",
"dateBroadcasted": "2024-01-10T19:02:12.873Z"
}

Typescript Example with Ethers

First install the Ethers JS. You can find the full documentation here: https://docs.ethers.org/v6/

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import { parseUnits, Transaction } from 'ethers'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'

const transaction = Transaction.from({
to: '0xa238b6008Bc2FBd9E386A5d4784511980cE504Cd',
value: '1',
gasLimit: '21000',
maxPriorityFeePerGas: parseUnits('5', 'gwei'),
maxFeePerGas: parseUnits('20', 'gwei'),
nonce: 3,
type: 2,
chainId: 11155111,
})

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: { kind: 'Transaction', transaction: transaction.unsignedSerialized },
})

Polkadot: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Polkadot, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x15020c0080610f0018000000e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423ec62bf1fb07fc43dafff5df75c691f4b74eb2b8647dbe5c5dc1b55e8912ce0ef6001bc9ffb0b7654778233f2708632ed39324a85919b5bf29386902f7d366111dd761b430010403003822eb5e88835101dd01b67f085a7544a44a6af91ea5516d4533c3a2447516dc419c00000000000000000000000000000000000000002048436865636b4e6f6e5a65726f53656e64657240436865636b5370656356657273696f6e38436865636b547856657273696f6e30436865636b47656e6573697338436865636b4d6f7274616c69747928436865636b4e6f6e63652c436865636b576569676874604368617267655472616e73616374696f6e5061796d656e7404"
}

200 response example

{
"id": "tx-2bbd9-7dvdf-xxxxxxxxxxxxxxxx",
"walletId": "wa-341e6-12nj6-xxxxxxxxxxxxxxxx",
"network": "Westend",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x15020c0080610f0018000000e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423ec62bf1fb07fc43dafff5df75c691f4b74eb2b8647dbe5c5dc1b55e8912ce0ef6001bc9ffb0b7654778233f2708632ed39324a85919b5bf29386902f7d366111dd761b430010403003822eb5e88835101dd01b67f085a7544a44a6af91ea5516d4533c3a2447516dc419c00000000000000000000000000000000000000002048436865636b4e6f6e5a65726f53656e64657240436865636b5370656356657273696f6e38436865636b547856657273696f6e30436865636b47656e6573697338436865636b4d6f7274616c69747928436865636b4e6f6e63652c436865636b576569676874604368617267655472616e73616374696f6e5061796d656e7404"
},
"status": "Broadcasted",
"txHash": "0xeef80db10b0341d8c4917a951e8156bce62f08f00ad8ef73dad9b640a161510f",
"dateRequested": "2024-02-08T20:19:38.428Z",
"dateBroadcasted": "2024-02-08T20:19:38.990Z"
}

Typescript Example with polkadot{.js}

First install the polkadot{.js} SDK. You can find the full documentation here: https://polkadot.js.org/docs/

Then install the txwrapper-core that has the tools needed to build a transaction.

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import { HttpProvider } from '@polkadot/api'
import { methods, getRegistry } from '@substrate/txwrapper-polkadot'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const httpProvider = new HttpProvider(POLKADOT_NODE_URL)

const {
block: {
header: { number: blockNumber },
},
} = (await httpProvider.send('chain_getBlock', [])) as any
const blockHash = (await httpProvider.send('chain_getBlockHash', [])) as string
const genesisHash = (await httpProvider.send('chain_getBlockHash', [0])) as string
const metadataRpc = (await httpProvider.send('state_getMetadata', [])) as `0x${string}`
const nonce = (await httpProvider.send('system_accountNextIndex', [senderWallet.address])) as number
const { specVersion, transactionVersion, specName } = (await httpProvider.send('state_getRuntimeVersion', [])) as any

const registry = getRegistry({
chainName: specName,
specName,
specVersion,
metadataRpc,
})

const unsigned = methods.balances.transferKeepAlive(
{
value: '10000',
dest: { id: '5DLJur1FsXezqiRvsq7nTJGDGszDW4xtNeENAYBMXPwPY9bZ' },
},
{
address: wallet.address,
blockHash,
blockNumber: parseInt(blockNumber, 16),
eraPeriod: 64,
genesisHash,
metadataRpc,
nonce,
specVersion,
tip: 0,
transactionVersion,
},
{
metadataRpc,
registry,
}
)

const signerPayload = registry.createType('SignerPayload', unsigned, {
version: unsigned.version,
})

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: { kind: 'Transaction', transaction: signerPayload.toHex() },
})

Solana: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Solana, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008001000103b25c8c464080ab2835a166d2b3f13195c2ff3c8f281c7ebe492f0d45d830ff4824a8b38a94b73d2756f2be68655a49706be9b1dc900978984d6eeaf65ab62e900000000000000000000000000000000000000000000000000000000000000000280c73cfb9caeb41b8508d20057917b568ac1f5a4175b5befa94532b3fd0b92e01020200010c02000000010000000000000000"
}

200 response example

{
"id": "tx-golst-ftnp9-xxxxxxxxxxxxxxxx",
"walletId": "wa-3i0nv-fa4e7-xxxxxxxxxxxxxxxx",
"network": "SolanaDevnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008001000103b25c8c464080ab2835a166d2b3f13195c2ff3c8f281c7ebe492f0d45d830ff4824a8b38a94b73d2756f2be68655a49706be9b1dc900978984d6eeaf65ab62e900000000000000000000000000000000000000000000000000000000000000000280c73cfb9caeb41b8508d20057917b568ac1f5a4175b5befa94532b3fd0b92e01020200010c02000000010000000000000000"
},
"status": "Broadcasted",
"txHash": "2VPvA6ekyrHT9TiH6YtcsjA5peXtSx8Er6q1yAUihBk2yimnjnU5CuBJLHsTXZxZV7JWSSffvaJ9uX8BB4ugconq",
"dateRequested": "2024-01-10T19:46:30.879Z",
"dateBroadcasted": "2024-01-10T19:46:31.399Z"
}

Typescript Example with Solana web3.js

First install the Solana web3.js SDK. You can find the full documentation here: https://docs.solana.com/developing/clients/javascript-api

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import {
clusterApiUrl,
Connection,
PublicKey,
SystemProgram,
TransactionMessage,
VersionedTransaction,
} from '@solana/web3.js'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const myAddress = new PublicKey(wallet.address)
const toAddress = new PublicKey('3U6stgsD1FmA7o3omUguritCU8iWmUM7Rs6KqAHHxHVZ')

const connection = new Connection(clusterApiUrl('devnet'), 'confirmed')
const latestBlockhash = await connection.getLatestBlockhash()

const message = new TransactionMessage({
payerKey: myAddress,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: myAddress,
toPubkey: toAddress,
lamports: 1n,
}),
],
}).compileToV0Message()
const transaction = new VersionedTransaction(message)

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${Buffer.from(transaction.serialize()).toString('hex')}`,
},
})

Stellar: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Stellar, always Transaction

transaction*

Hex

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x0000000200000000df9fecfd6871f56a3ba3d875d295444be08d6b5f38d0ef56901b85e386a84ff1000000640013d1d800000016000000010000000000000000000000006633f4e3000000010000000631323334353600000000000100000000000000010000000033659e6d03936b7746c8a8904bac95d5f582c2a0bb32b8a5a8e1f10e6d2b869d0000000000000000000000010000000000000000"
}

200 response example

{
"id": "tx-4439u-fm76a-xxxxxxxxxxxxxxxx",
"walletId": "wa-46sdf-a9stj-xxxxxxxxxxxxxxxx",
"network": "StellarTestnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x0000000200000000df9fecfd6871f56a3ba3d875d295444be08d6b5f38d0ef56901b85e386a84ff1000000640013d1d800000016000000010000000000000000000000006633f4e3000000010000000631323334353600000000000100000000000000010000000033659e6d03936b7746c8a8904bac95d5f582c2a0bb32b8a5a8e1f10e6d2b869d0000000000000000000000010000000000000000"
},
"status": "Broadcasted",
"txHash": "f25d140537c696b4672ed9a134e8889c8d381b52d238919b8108ba214bff86ee",
"dateRequested": "2024-05-02T20:14:41.260Z",
"dateBroadcasted": "2024-05-02T20:14:41.980Z"
}

Typescript Example with Stellar SDK

First install the Stellar SDK. You can find the full documentation here: https://stellar.github.io/js-stellar-sdk/

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import { Asset, BASE_FEE, Horizon, Networks, Operation, TransactionBuilder } from '@stellar/stellar-sdk'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const provider = new Horizon.Server(process.env.HORIZON_API_URL!)

const account = await provider.loadAccount(senderWallet.address)
const transaction = new TransactionBuilder(account, {
fee: BASE_FEE,
networkPassphrase: Networks.TESTNET,
})
.addOperation(
Operation.payment({
destination: 'GAZWLHTNAOJWW52GZCUJAS5MSXK7LAWCUC5TFOFFVDQ7CDTNFODJ37GB',
asset: Asset.native(),
amount: '1',
})
)
.setTimeout(180)
.build()

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${transaction.toEnvelope().toXDR('hex')}`,
},
})

Tezos: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Tezos, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x04c4b1966777a5d83f3f61e17bf64aa6090ddd3413ede4e24316d3334a7836486c0060f4b0700cb1b73bff168a6221c6a033de12953ebc029d82d50a8d02000100008017ed86b1bbb1c6a9399fc47b83fb8a919e013400"
}

200 response example

{
"id": "tx-5fnhg-8u56n-xxxxxxxxxxxxxxxx",
"walletId": "wa-5kqa8-4leor-xxxxxxxxxxxxxxxx",
"network": "TezosGhostnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x04c4b1966777a5d83f3f61e17bf64aa6090ddd3413ede4e24316d3334a7836486c0060f4b0700cb1b73bff168a6221c6a033de12953ebc029d82d50a8d02000100008017ed86b1bbb1c6a9399fc47b83fb8a919e013400"
},
"status": "Broadcasted",
"txHash": "ooESkzFG4oKQueVWX9PX1tSrBES8hWJ7N9NRtz2gK6AwVZpZqGX",
"dateRequested": "2024-01-10T20:06:52.915Z",
"dateBroadcasted": "2024-01-10T20:06:53.103Z"
}

Typescript Example with Taquito

First install the Taquito SDK. You can find the full documentation here: https://taquito.io/docs/quick_start/

Taquito is a little special in that it requires a signer to forge an operation. In fact, we only need the signer to return the wallet address and the encoded public key. We'll initialize a Taquito RPC instance using our fake signer and a local forger (see below). After forging the operation, we can distribute it via the Dfns TypeScript SDK.

import { RpcClient } from '@taquito/rpc'
import { Signer, TezosToolkit } from '@taquito/taquito'
import { LocalForger } from '@taquito/local-forging'
import { Prefix, b58cencode, prefix } from '@taquito/utils'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

// Tezos requires a signer to forge a transaction. When forging, we only
// need 'publicKeyHash' (address) and 'publicKey' (encoded)
class TezosToolkitSigner implements Signer {
sign(): Promise<{
bytes: string
sig: string
prefixSig: string
sbytes: string
}> {
throw new Error('Method not implemented.')
}
async publicKey(): Promise<string> {
const prefix = wallet.signingKey.scheme === 'EdDSA' ? Prefix.EDPK : Prefix.SPPK
return b58cencode(wallet.signingKey.publicKey, prefix)
}

async publicKeyHash(): Promise<string> {
return wallet.address
}

secretKey(): Promise<string | undefined> {
throw new Error('Method not implemented.')
}
}

const client = new RpcClient('TEZOS_NODE_URL')
const Tezos = new TezosToolkit(client)
const forger = new LocalForger()

Tezos.setForgerProvider(forger)
Tezos.setSignerProvider(new TezosToolkitSigner())

const receiver = 'tz1XKKrD4NLRhBK4PFxQ4XvH2KXZ6J389N1Z'

// estimate fees
const estimate = await Tezos.estimate.transfer({
source: wallet.address,
to: receiver,
amount: 1,
})

const prepared = await Tezos.prepare.transaction({
source: wallet.address,
to: receiver,
amount: 1,
fee: estimate.suggestedFeeMutez,
gasLimit: estimate.gasLimit,
storageLimit: estimate.storageLimit,
})

const forgeable = await Tezos.prepare.toForge(prepared)
const forgedBytes = await forger.forge(forgeable)

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${forgedBytes}`,
},
})

Tezos: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Tezos, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x04c4b1966777a5d83f3f61e17bf64aa6090ddd3413ede4e24316d3334a7836486c0060f4b0700cb1b73bff168a6221c6a033de12953ebc029d82d50a8d02000100008017ed86b1bbb1c6a9399fc47b83fb8a919e013400"
}

200 response example

{
"id": "tx-5fnhg-8u56n-xxxxxxxxxxxxxxxx",
"walletId": "wa-5kqa8-4leor-xxxxxxxxxxxxxxxx",
"network": "TezosGhostnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x04c4b1966777a5d83f3f61e17bf64aa6090ddd3413ede4e24316d3334a7836486c0060f4b0700cb1b73bff168a6221c6a033de12953ebc029d82d50a8d02000100008017ed86b1bbb1c6a9399fc47b83fb8a919e013400"
},
"status": "Broadcasted",
"txHash": "ooESkzFG4oKQueVWX9PX1tSrBES8hWJ7N9NRtz2gK6AwVZpZqGX",
"dateRequested": "2024-01-10T20:06:52.915Z",
"dateBroadcasted": "2024-01-10T20:06:53.103Z"
}

Typescript Example with Taquito

First install the Taquito SDK. You can find the full documentation here: https://taquito.io/docs/quick_start/

Taquito is a little special in that it requires a signer to forge an operation. In fact, we only need the signer to return the wallet address and the encoded public key. We'll initialize a Taquito RPC instance using our fake signer and a local forger (see below). After forging the operation, we can distribute it via the Dfns TypeScript SDK.

import { RpcClient } from '@taquito/rpc'
import { Signer, TezosToolkit } from '@taquito/taquito'
import { LocalForger } from '@taquito/local-forging'
import { Prefix, b58cencode, prefix } from '@taquito/utils'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

// Tezos requires a signer to forge a transaction. When forging, we only
// need 'publicKeyHash' (address) and 'publicKey' (encoded)
class TezosToolkitSigner implements Signer {
sign(): Promise<{
bytes: string
sig: string
prefixSig: string
sbytes: string
}> {
throw new Error('Method not implemented.')
}
async publicKey(): Promise<string> {
const prefix = wallet.signingKey.scheme === 'EdDSA' ? Prefix.EDPK : Prefix.SPPK
return b58cencode(wallet.signingKey.publicKey, prefix)
}

async publicKeyHash(): Promise<string> {
return wallet.address
}

secretKey(): Promise<string | undefined> {
throw new Error('Method not implemented.')
}
}

const client = new RpcClient('TEZOS_NODE_URL')
const Tezos = new TezosToolkit(client)
const forger = new LocalForger()

Tezos.setForgerProvider(forger)
Tezos.setSignerProvider(new TezosToolkitSigner())

const receiver = 'tz1XKKrD4NLRhBK4PFxQ4XvH2KXZ6J389N1Z'

// estimate fees
const estimate = await Tezos.estimate.transfer({
source: wallet.address,
to: receiver,
amount: 1,
})

const prepared = await Tezos.prepare.transaction({
source: wallet.address,
to: receiver,
amount: 1,
fee: estimate.suggestedFeeMutez,
gasLimit: estimate.gasLimit,
storageLimit: estimate.storageLimit,
})

const forgeable = await Tezos.prepare.toForge(prepared)
const forgedBytes = await forger.forge(forgeable)

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${forgedBytes}`,
},
})

TRON: Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For Tron, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x0a83010a0228222208b142ad939b228d784090a7eaa9cf315a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15419d31b91d72b58d7c8c02a7124410e168989f372d12154102a69d5d85c05864dc6fd74f57db3fa37aff7b94180170b0d2e6a9cf31"
}

200 response example

{
"id": "tx-19u01-g60tf-xxxxxxxxxxxxxxxx",
"walletId": "wa-174tk-m918i-xxxxxxxxxxxxxxxx",
"network": "TronNile",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x0a83010a0228222208b142ad939b228d784090a7eaa9cf315a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15419d31b91d72b58d7c8c02a7124410e168989f372d12154102a69d5d85c05864dc6fd74f57db3fa37aff7b94180170b0d2e6a9cf31"
},
"status": "Broadcasted",
"txHash": "ecd735b16e4b77b3b791071a4df8645c503b846afec3888cca33c777e78ad3a4",
"dateRequested": "2024-01-10T21:14:17.979Z",
"dateBroadcasted": "2024-01-10T21:14:18.166Z"
}

Typescript Example with TronWeb

First install TronWeb. You can find the full documentation here: https://tronweb.network/docu/docs/intro/

Tron requires the transaction to be serialized using the protobuf format before it can be broadcast. As it's not trivial, you can use the functions exposed in Tronweb to generate the transaction in the right format (see below) and then broadcast via the Dfns TypeScript SDK:

const TronWeb = require('tronweb')

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const transaction = await tronWeb.transactionBuilder.sendTrx('TADDx31pdCFfp3XrYxp6fQGbRxriYFLTrx', 1000, wallet.address)

const txPb = TronWeb.utils.transaction.txJsonToPb(transaction)

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${TronWeb.utils.bytes.byteArray2hexStr(txPb.serializeBinary())}`,
},
})

XRP Ledger (aka Ripple): Broadcast Transaction

Request body

Property

Type

Description

kind*

String

For XRP Ledger, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x120000220000000024029a62a82e0001e240201b02a6243661400000000000000168400000000000000c8114860184b4f4c6cc17ae9c2a77cfcd328b43ec2aac8314543aba55a3bede29c5d512ff0cb17db626b9ed9a"
}

200 response example

{
"id": "tx-60es5-5sc68-xxxxxxxxxxxxxxxx",
"walletId": "wa-4ih27-hei2f-xxxxxxxxxxxxxxxx",
"network": "RippleTestnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x120000220000000024029a62a82e0001e240201b02a6243661400000000000000168400000000000000c8114860184b4f4c6cc17ae9c2a77cfcd328b43ec2aac8314543aba55a3bede29c5d512ff0cb17db626b9ed9a"
},
"status": "Broadcasted",
"txHash": "7C3668AB82CC55648F784E9C782B6FFA65D0B37C8D2D57B821D505C0DAF27197",
"dateRequested": "2024-01-10T21:19:57.605Z",
"dateBroadcasted": "2024-01-10T21:19:58.225Z"
}

Typescript Example with xrpl.js

First install xrpl.js. You can find the full documentation here: https://js.xrpl.org/

Here a code sample to broadcast a transaction via the Dfns TypeScript SDK:

import { Client, encode } from 'xrpl'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const client = new Client(RIPPLE_NODE_URL)
await client.connect()

const transaction = await client.autofill({
TransactionType: 'Payment',
Account: wallet.address,
Destination: 'rBYtCQKxGTfFuob3hxSc8pEYddetT9CdDZ',
Amount: '1',
})

const res = await dfnsClient.wallets.broadcastTransaction({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${encode(transaction).toLowerCase()}`,
},
})

Get Wallet Transaction Request by ID

GET /wallets/{walletId}/transactions/{transactionId}

Retrieves a Wallet Transaction Request by its ID.

Required Permissions

Name

Conditions

Wallets:ReadTransaction

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex.wa-6lbvd-hjdu1-xxxxxxxxxxxxxxxx

transactionId

Unique identifier of the transaction request. ex. tx-1jbko-fmk8d-xxxxxxxxxxxxxxxx

Response

200 Response example

{
"id": "tx-1jbko-fmk8d-xxxxxxxxxxxxxxxx",
"walletId": "wa-6lbvd-hjdu1-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Evm",
"to": "0xb282dc7cde21717f18337a596e91ded00b79b25f",
"value": "1000000000"
},
"status": "Confirmed",
"txHash": "0x1e62ce5cf14b026d8fe3b5fa6195857049ec22e55fe932c74598c21866c07f14",
"fee": "31500000147000",
"dateRequested": "2023-05-09T19:51:33.628Z",
"dateBroadcasted": "2023-05-09T19:51:39.983Z",
"dateConfirmed": "2023-05-09T19:51:48.000Z",
"approvalId": "ap-...", // defined only if an approval process was triggered as the result of a policy ("status" will be "Pending" then)
}

List Wallet Transaction Requests

GET /wallets/{walletId}/transactions?paginationToken={token}

Retrieves a list of transactions requests for the specified wallet.

Required Permissions

Name

Conditions

Wallets:ReadTransaction

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex.wa-6lbvd-hjdu1-xxxxxxxxxxxxxxxx

Query parameters

Query string parameter

Required/Optional

Description

Type

limit

Optional

Maximum number of items to return. Default to 50.

Number

paginationToken

Optional

Opaque token used to retrieve the next page. Returned as nextPageToken from the previous request.

String

Response

200 Response example

{
"walletId": "wa-6lbvd-hjdu1-xxxxxxxxxxxxxxxx",
"items": [
{
"id": "tx-214gn-efbru-xxxxxxxxxxxxxxxx",
"walletId": "wa-6lbvd-hjdu1-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Evm",
"to": "0x00fb58432ef9d418bf6688bcf0a226d2fcaa18e2",
"data": "0x40d097c3000000000000000000000000d2f77f85a50cdd650ca562f3a180284e1d5b4934"
},
"status": "Confirmed",
"txHash": "0x192948dae1bb4cd5765f46417fbfbe500c413f9947dab89184ef3ecd16117640",
"fee": "93636000499392",
"dateRequested": "2023-05-10T22:23:44.742Z",
"dateBroadcasted": "2023-05-10T22:23:51.887Z",
"dateConfirmed": "2023-05-10T22:24:00.000Z"
},
...
],
"nextPageToken": "WszQXoENUIYyoBQjJm4DE6QhCk2sB7WAh9kykUMaTQcD25SToKbuXkgf3td8ZYb2LrtopPLo35u407gwwA1Sug=="
}

Generate Signature from Wallet

POST /wallets/{walletId}/signatures

Request to generate a signature with the wallet key. This process does not broadcast anything on-chain, this is just an off-chain signature request.

Required Permissions

Name

Conditions

Wallets:GenerateSignature

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Request Body

The body of the request will depend on the chain you are targeting. Please find the chain in question by expanding this section in the left hand navigation:

Response Statuses

Status

Definition

Pending

The request is pending approval due to a policy applied to the wallet

Executing

The request is approved and is in the process of being signed (note this status is only set for a short time between pending and signed)

Signed

The signature is complete and available in the response body

Confirmed

The signature has been confirmed on-chain by our indexing pipeline

Failed

Indicates an internal system failure to complete the request

Rejected

The request has been rejected by a policy approval action

Algorand: Generate Signature

Request body

Property

Type

Description

kind*

String

For Algorand, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x81a374786e89a3616d7401a3666565cd03e8a26676ce0233fc92a367656eac746573746e65742d76312e30a26768c4204863b518a4b3c84ec810f22d4f1081cb0f71f059a7ac20dec62f7f70e5093a22a26c76ce0234007aa3726376c4202c72fe6b78fb1ac99b8e72c9224a6f114c63e598fc1bcf6b048012ae9fc4730aa3736e64c4201256a859b39429ee178e0a65056fb33d51c5139044f6a2603c144278010c7684a474797065a3706179"
}

200 response example

{
"id": "sig-4gkdv-j61d9-xxxxxxxxxxxxxxxx",
"walletId": "wa-341e6-12nj6-xxxxxxxxxxxxxxxx",
"network": "AlgorandTestnet",
"requester": {
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x81a374786e89a3616d7401a3666565cd03e8a26676ce0233fc92a367656eac746573746e65742d76312e30a26768c4204863b518a4b3c84ec810f22d4f1081cb0f71f059a7ac20dec62f7f70e5093a22a26c76ce0234007aa3726376c4202c72fe6b78fb1ac99b8e72c9224a6f114c63e598fc1bcf6b048012ae9fc4730aa3736e64c4201256a859b39429ee178e0a65056fb33d51c5139044f6a2603c144278010c7684a474797065a3706179"
},
"status": "Signed",
"signature": {
"r": "0x134ef556b3409f9888b0c7613ca5eeb5e9dc2df62fbcc48ca2be3c3f2d3ca7f5",
"s": "0x2477ff80eb235b12e534ab98261cf24dbdf38a6acbe0426551e9caa3c3c07702",
"encoded": "0x134ef556b3409f9888b0c7613ca5eeb5e9dc2df62fbcc48ca2be3c3f2d3ca7f52477ff80eb235b12e534ab98261cf24dbdf38a6acbe0426551e9caa3c3c07702"
},
"signedData": "0x82a3736967c440134ef556b3409f9888b0c7613ca5eeb5e9dc2df62fbcc48ca2be3c3f2d3ca7f52477ff80eb235b12e534ab98261cf24dbdf38a6acbe0426551e9caa3c3c07702a374786e89a3616d7401a3666565cd03e8a26676ce0233fc92a367656eac746573746e65742d76312e30a26768c4204863b518a4b3c84ec810f22d4f1081cb0f71f059a7ac20dec62f7f70e5093a22a26c76ce0234007aa3726376c4202c72fe6b78fb1ac99b8e72c9224a6f114c63e598fc1bcf6b048012ae9fc4730aa3736e64c4201256a859b39429ee178e0a65056fb33d51c5139044f6a2603c144278010c7684a474797065a3706179",
"dateRequested": "2024-02-08T16:40:21.866Z",
"dateSigned": "2024-02-08T16:40:22.387Z"
}

Typescript Example with AlgoSDK

First install the AlgoSDK. You can find the full documentation here: https://github.com/algorand/js-algorand-sdk

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import { Algodv2, encodeObj, makePaymentTxnWithSuggestedParamsFromObject } from 'algosdk'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const algod = new Algodv2(ALGORAND_TOKEN, ALGORAND_NODE_URL)

const suggestedParams = await algod.getTransactionParams().do()
const transaction = makePaymentTxnWithSuggestedParamsFromObject({
from: wallet.address,
suggestedParams,
to: 'CJLKQWNTSQU64F4OBJSQK35THVI4KE4QIT3KEYB4CRBHQAIMO2CD6JWBCY',
amount: 10000,
})

const bytes = encodeObj({ txn: transaction.get_obj_for_encoding() })

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${Buffer.from(bytes).toString('hex')}`,
},
})

Bitcoin/Litecoin: Generate Signature

Bitcoin and Litecoin chains support the following signature kinds:

  • Psbt: Fully sign a PSBT, partially signed bitcoin transaction.

  • Bip322: Generates the signature for a generic message defined in BIP-322.

PSBT Signature

Property

Type

Description

kind*

String

Psbt

psbt*

Hex String

The hex encoded PSBT as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Psbt",
"psbt": "0x70736274ff0100710200000001ca17431a33a13d3ef8bfb041c8546071f9d3a609abe3c91efbed83265e1426730100000000ffffffff02e803000000000000160014a40a65b46ff36c53f1afb8e35e25a4c0bcfc9979d6d1150000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000000001011f54d6150000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000"
}

200 response example

{
"id": "sig-7dmih-01orr-xxxxxxxxxxxxxxxx",
"walletId": "wa-36a0p-pdil7-xxxxxxxxxxxxxxxx",
"network": "BitcoinTestnet3",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Psbt",
"psbt": "0x70736274ff0100710200000001cd290edbff81f3762b1c9a6f6532f5f2d3d1e48a850d4285b8606bbceb96ee790000000000ffffffff020100000000000000160014a40a65b46ff36c53f1afb8e35e25a4c0bcfc99794d25000000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000000001011fe425000000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000"
},
"status": "Signed",
"signatures": [
{
"r": "0xe10a3e24bb0b0a5feae39997d05b5d1ce0e123f78c979914ea3394962f7995f6",
"s": "0x727190270d14e58acbcfa98a765fd4c50b51afb7d1ef8152cd79d562f28a1bbc",
"recid": 0,
"encoded": "0x3045022100e10a3e24bb0b0a5feae39997d05b5d1ce0e123f78c979914ea3394962f7995f60220727190270d14e58acbcfa98a765fd4c50b51afb7d1ef8152cd79d562f28a1bbc"
}
],
"signedData": "0x70736274ff0100710200000001cd290edbff81f3762b1c9a6f6532f5f2d3d1e48a850d4285b8606bbceb96ee790000000000ffffffff020100000000000000160014a40a65b46ff36c53f1afb8e35e25a4c0bcfc99794d25000000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9000000000001011fe425000000000000160014237ad8ba2ffd992f6ebc7ab388e77f00fc87d1c9220203e6be69fe373e07962698243fb3d41b5b24e16a461866bd1813afcf9b53e1da6e483045022100e10a3e24bb0b0a5feae39997d05b5d1ce0e123f78c979914ea3394962f7995f60220727190270d14e58acbcfa98a765fd4c50b51afb7d1ef8152cd79d562f28a1bbc01000000",
"dateRequested": "2024-01-10T19:15:21.572Z",
"dateSigned": "2024-01-10T19:15:21.859Z"
}

Typescript Example with BitcoinJS

First install the BitcoinJS SDK. You can find the full documentation here: https://github.com/bitcoinjs/bitcoinjs-lib

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import { networks, payments, Psbt } from 'bitcoinjs-lib'
import axios from 'axios'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })
const publicKey = Buffer.from(wallet.signingKey.publicKey, 'hex')

const network = networks.testnet
const { address } = payments.p2wpkh({
pubkey: publicKey,
network,
})

const txid = '87872516c6e93f136fc6c493c7172596b11c695e27889de7532abffcac2a4b5e'
const n = 1
const utxo = (
await axios.post(BITCOIN_NODE_URL, {
jsonrpc: '2.0',
id: 'gettxout',
method: 'gettxout',
params: [txid, n, false],
})
).data.result

const balance = utxo.balance * 100000000
const amount = 1
const fee = 150

const psbt = new Psbt({ network })
psbt.addInput({
hash: txid,
index: n,
witnessUtxo: {
script: Buffer.from(utxo.scriptPubKey.hex, 'hex'),
value: balance,
},
})

psbt.addOutput({
address: 'tb1q5s9xtdr07dk98ud0hr34ufdycz70exte2kehm2',
value: amount,
})

psbt.addOutput({
address,
value: balance - amount - fee,
})

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: { kind: 'Psbt', psbt: `0x${psbt.toHex()}` },
})

BIP-322 Generic Message Signature

Generates the signature for a generic message defined in BIP-322.

Request body

Property

Type

Description

kind*

String

Bip322

message*

String

The generic message hex encoded.

format

(Optional) String

Either Simple or Full. Defaults to Simple if not present. The formatted signature is returned in the signedData field in the response.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Bip322",
"message": "0x49206c6f76652044666e73"
}

200 response example

{
"id": "sig-7dmih-01orr-xxxxxxxxxxxxxxxx",
"walletId": "wa-36a0p-pdil7-xxxxxxxxxxxxxxxx",
"network": "BitcoinTestnet3",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Bip322",
"hash": "0x49206c6f76652044666e73"
},
"status": "Signed",
"signature": {
"r": "0x883613c2f19e4ab70f82c533950fb9060ac366a3a64d77950c89866dfe07c926",
"s": "0x3fb815f34db5ebc9e97dee46500b75494717cb69adec5f01e17b4a58c50f9bfa",
"recid": 1,
"encoded": "0x3045022100883613c2f19e4ab70f82c533950fb9060ac366a3a64d77950c89866dfe07c92602203fb815f34db5ebc9e97dee46500b75494717cb69adec5f01e17b4a58c50f9bfa"
},
"signedData": "0x02483045022100883613c2f19e4ab70f82c533950fb9060ac366a3a64d77950c89866dfe07c92602203fb815f34db5ebc9e97dee46500b75494717cb69adec5f01e17b4a58c50f9bfa012103e6be69fe373e07962698243fb3d41b5b24e16a461866bd1813afcf9b53e1da6e",
"dateRequested": "2024-10-25T17:47:48.068Z",
"dateSigned": "2024-10-25T17:47:48.749Z"
}

Cardano: Generate Signature

Request body

Property

Type

Description

kind*

String

For Cardano, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x84a3008182582082544414292ededfa716ae42af007ecff823c58796cb9ba60330699fb4d55d7901018282581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621a000cf4ae82581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621b0000000253db20cd021a00028785a0f5f6"
}

200 response example

{
"id": "sig-65s39-hsdh3-xxxxxxxxxxxxxxxx",
"walletId": "wa-7nej2-e3o6d-xxxxxxxxxxxxxxxx",
"network": "CardanoPreprod",
"requester": {
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x84a3008182582082544414292ededfa716ae42af007ecff823c58796cb9ba60330699fb4d55d7901018282581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621a000cf4ae82581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621b0000000253db20cd021a00028785a0f5f6"
},
"status": "Signed",
"signature": {
"r": "0x92e520787d6ca35a3e412fa81890a5fd9299e4d8f9ad23dbff284d2e970dce18",
"s": "0xe7721b4cc8b5a5190605f6e29833c8af1b9e3f5388927e4bd453f630a841bf08",
"encoded": "0x92e520787d6ca35a3e412fa81890a5fd9299e4d8f9ad23dbff284d2e970dce18e7721b4cc8b5a5190605f6e29833c8af1b9e3f5388927e4bd453f630a841bf08"
},
"signedData": "0x84a3008182582082544414292ededfa716ae42af007ecff823c58796cb9ba60330699fb4d55d7901018282581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621a000cf4ae82581d60112f2721059581f2a8f9986638359b83c567a61d5486ed0e16c818621b0000000253db20cd021a00028785a10081825820b6332924a382b07808174ae732e8f7ffc32f9955197f25e8b92e93ac6924658a584092e520787d6ca35a3e412fa81890a5fd9299e4d8f9ad23dbff284d2e970dce18e7721b4cc8b5a5190605f6e29833c8af1b9e3f5388927e4bd453f630a841bf08f5f6",
"dateRequested": "2024-05-09T16:21:36.949Z",
"dateSigned": "2024-05-09T16:21:37.809Z"
}

Typescript Example with MeshJS SDK

First install the MeshJS SDK. You can find the full documentation here: https://docs.meshjs.dev/

You also need a service that tracks the account's UTXO, for example Blockfrost. The Dfns TypeScript SDK has an example demonstrating how to write a custom Blockfrost initiator plugin for MeshJS.

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import { BlockfrostProvider, Transaction } from '@meshsdk/core'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const provider = new BlockfrostProvider(process.env.BLOCKFROST_PROJECT_ID!)
const initiator = new CustomInitiator(wallet.address, provider)

const transaction = await new Transaction({ initiator })
.sendLovelace('addr_test1vq5eele9enryyqkg4wrjyp7x4gpshvkr6rylkwtyau56g3qgrcks9', '1000000')
.build()

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${transaction}`,
},
})

Cosmos Appchain: Generate Signature

SIGN_MODE_DIRECT Signature

Generates the signature using SIGN_MODE_DIRECT.

Property

Type

Description

kind*

String

SignDocDirect

signDoc*

Hex String

The hex encoded SignDoc protobuf as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "SignDocDirect",
"signDoc": "0x0a89010a86010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e6412660a2b6f736d6f313366796d6d61797430727a72366d6130716439686a6d71747433706b37787737736871666b70122b6f736d6f313378396b70343573366e6539686a6738356b333867346d7a687067337435766a666c30356b6c1a0a0a05756f736d6f12013112640a4e0a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a210286a1b7ce6ae2b5b33c47d0b6c91bb28e4cdb786d15f4497adcdaa69640ca0db512040a02080112120a0c0a05756f736d6f120337353010e0a7121a0b6f736d6f2d746573742d3520e39f06"
}

200 response example

{
"id": "sig-7jb9u-37kf5-xxxxxxxxxxxxxxxx",
"walletId": "wa-4a2t4-fjvpo-xxxxxxxxxxxxxxxx",
"network": "SeiAtlantic2",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "SignDocDirect",
"transaction": "0x0a89010a86010a1c2f636f736d6f732e62616e6b2e763162657461312e4d736753656e6412660a2b6f736d6f313366796d6d61797430727a72366d6130716439686a6d71747433706b37787737736871666b70122b6f736d6f313378396b70343573366e6539686a6738356b333867346d7a687067337435766a666c30356b6c1a0a0a05756f736d6f12013112640a4e0a460a1f2f636f736d6f732e63727970746f2e736563703235366b312e5075624b657912230a210286a1b7ce6ae2b5b33c47d0b6c91bb28e4cdb786d15f4497adcdaa69640ca0db512040a02080112120a0c0a05756f736d6f120337353010e0a7121a0b6f736d6f2d746573742d3520e39f06"
},
"status": "Signed",
"signature": {
"r": "0x96cfe730ef5edc727c29ace118aac11cf70f031d05be4b9a7cb24ebe7caa7cf5",
"s": "0x3646b908c79eb310b4d56c2e23daf64ee14ceed8155779b83aebd3aef7c8fb4a",
"recid": 1,
"encoded": "0x96cfe730ef5edc727c29ace118aac11cf70f031d05be4b9a7cb24ebe7caa7cf53646b908c79eb310b4d56c2e23daf64ee14ceed8155779b83aebd3aef7c8fb4a"
},
"dateRequested": "2024-10-18T21:29:40.779Z",
"dateSigned": "2024-10-18T21:29:41.299Z"
}

Typescript Example with CosmJS SDK

First install the CosmJS SDK. You can find the full documentation here: https://cosmos.github.io/cosmjs/

Here a code sample to generate a signature via the Dfns TypeScript SDK:

const client = await Comet38Client.create(new HttpClient(process.env.OSMOSIS_NODE_URL!))
const queryClient = QueryClient.withExtensions(cometClient, setupAuthExtension)

const body: TxBodyEncodeObject = {
typeUrl: '/cosmos.tx.v1beta1.TxBody',
value: {
messages: [
{
typeUrl: '/cosmos.bank.v1beta1.MsgSend',
value: {
fromAddress: address,
toAddress: to,
amount: coins(1, 'uosmo'),
},
},
],
memo,
},
}

const account = await context.queryClient.auth.account(address)
const { sequence, accountNumber } = accountFromAny(account)

const authInfoBytes = makeAuthInfoBytes(
[
{
pubkey: encodePubkey(encodeSecp256k1Pubkey(Buffer.from(publicKey, 'hex'))),
sequence,
},
],
'100',
Int53.fromString(fee.gas).toNumber(),
undefined,
undefined
)

const signDoc = makeSignDoc(context.registry.encode(body), authInfoBytes, 'osmo-test-5', accountNumber)

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'SignDocDirect',
signDoc: `0x${Buffer.from(makeSignBytes(doc)).toString('hex')}`,
},
})

EVM: Generate Signature

EVM chains like Ethereum, Polygon, BSC, Arbitrum, etc support the following signature kinds:

  • Transaction: Generates a fully signed transaction ready for broadcasting yourself.

  • Message: Generates a signature for an arbitrary message.

  • Eip712: Generates the signature for typed structured data defined in EIP-712.

  • Hash: Generates the signature for the hash digest of the original message.

Transaction Signature

Generates a fully signed transaction ready for broadcasting yourself.

Property

Type

Description

kind*

String

Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"message": "0x02e783aa36a71503850d40e49def82520894e5a2ebc128e262ab1e3bd02bffbe16911adfbffb0180c0"
}

200 response example

{
"id": "sig-39l22-xxxxx-xxxxxxxxxxxxxxxx",
"walletId": "wa-19lns-xxxxx-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-xxxxx-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-xxxxx-xxxxxxxxxxxxxxxx",
"appId": "ap-c831n-xxxxx-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x02e783aa36a71603850cbab1770382520894e5a2ebc128e262ab1e3bd02bffbe16911adfbffb0180c0"
},
"status": "Signed",
"signature": {
"r": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c",
"s": "0x47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f14a63da7ce5a1fe",
"recid": 0,
"encoded": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f10000000000000000"
},
"signedData": "0x02f86a83aa36a71603850cbab1770382520894e5a2ebc128e262ab1e3bd02bffbe16911adfbffb0180c080a005e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6ca047e0765c439fb42d57767910865d240964b7b09f2b2f74d80000000000000000",
"dateRequested": "2024-01-10T19:07:39.277Z",
"dateSigned": "2024-01-10T19:07:40.533Z"
}

Typescript Example with Ethers

First install the Ethers JS. You can find the full documentation here: https://docs.ethers.org/v6/

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import { parseUnits, Transaction } from 'ethers'

const walletId = 'wa-6lbfv-9esgj-88s80c0qsih0a393'

const transaction = Transaction.from({
to: '0xa238b6008Bc2FBd9E386A5d4784511980cE504Cd',
value: '1',
gasLimit: '21000',
maxPriorityFeePerGas: parseUnits('5', 'gwei'),
maxFeePerGas: parseUnits('20', 'gwei'),
nonce: 3,
type: 2,
chainId: 11155111,
})

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: { kind: 'Transaction', transaction: transaction.unsignedSerialized },
})

Message Signature

Generates a signature for an arbitrary message.

Property

Type

Description

kind*

String

Message

message*

String

The original message hex encoded.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Message",
"message": "0x49206c6f76652044666e73"
}

200 response example

{
"id": "sig-2rv2t-u0cmd-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "KeyEdDSA",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Message",
"message": "0x49206c6f76652044666e73"
},
"status": "Signed",
"signature": {
"r": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c",
"s": "0x47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f14a63da7ce5a1fe",
"recid": 0,
"encoded": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f10000000000000000"
},
"dateRequested": "2023-05-15T20:21:11.576Z",
"dateSigned": "2024-01-10T19:07:40.533Z"
}

EIP-712 TypedData Signature

Generates the signature for typed structured data defined in EIP-712, only applicable for EVM compatible blockchain networks.

field

Type

Description

kind*

String

Eip712

types*

Map<String, TypedDataField[]>

Type definitions.

domain*

Eip712Domain

Domain separator.

message*

Object

Structured message to sign.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

TypedDataField

field

Type

Description

name*

String

Field name.

type*

String

Field type.

Eip712Domain

field

Type

Description

name

String

Name of the signing domain.

version

String

Current major version of the signing domain.

chainId

Integer

Chain ID.

verifyingContract

String

The address of the contract that will verify the signature.

salt

String

32-byte value as a last-resort domain separator.

Sample request body

{
"kind": "Eip712",
"types": {
"Person": [
{ "name": "name", "type": "string" },
{ "name": "wallet", "type": "address" }
],
"Mail": [
{ "name": "from", "type": "Person" },
{ "name": "to", "type": "Person" },
{ "name": "contents", "type": "string" }
]
},
"domain": {
"name": "Ether Mail",
"version": "1",
"chainId": 1,
"verifyingContract": "0x1b352de7a926ebd1bf52194dab487c2cb0793a9b",
"salt": "0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558"
},
"message": {
"from": {
"name": "Chris",
"wallet": "0x00e3495cf6af59008f22ffaf32d4c92ac33dac47"
},
"to": {
"name": "Bob",
"wallet": "0xcc0ee1a1c5e788b61916c8f1c96c960f9a9d3db7"
},
"contents": "Hello, Bob!"
}
}

200 response example

{
"id": "sig-4tcfd-enph7-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Eip712",
"types": {
"Person": [
{
"name": "name",
"type": "string"
},
{
"name": "wallet",
"type": "address"
}
],
"Mail": [
{
"name": "from",
"type": "Person"
},
{
"name": "to",
"type": "Person"
},
{
"name": "contents",
"type": "string"
}
]
},
"domain": {
"name": "Ether Mail",
"version": "1",
"chainId": 1,
"verifyingContract": "0x1b352de7a926ebd1bf52194dab487c2cb0793a9b",
"salt": "0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558"
},
"message": {
"from": {
"name": "Chris",
"wallet": "0x00e3495cf6af59008f22ffaf32d4c92ac33dac47"
},
"to": {
"name": "Bob",
"wallet": "0xcc0ee1a1c5e788b61916c8f1c96c960f9a9d3db7"
},
"contents": "Hello, Bob!"
}
},
"status": "Signed",
"signature": {
"r": "0xb23c2cfb6d409f5a55ced08f89ae70f3fe89403a5ba907c367545499874f1c7f",
"s": "0x49992f242a21ae0692c24b43393336744ddc08459d936b6a70542d79df4f66f0",
"recid": 1,
"encoded": "0xb23c2cfb6d409f5a55ced08f89ae70f3fe89403a5ba907c367545499874f1c7f49992f242a21ae0692c24b43393336744ddc08459d936b6a70542d79df4f66f01c"
},
"dateRequested": "2023-05-15T19:26:18.145Z"
}

Hash Signature

Generates the signature for the hash digest of the original message.

Request body

Property

Type

Description

kind*

String

Hash

hash*

String

The hash digest in hex.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Hash",
"hash": "031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406"
}

200 response example

{
"id": "sig-2ouaj-f4nq6-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Hash",
"hash": "031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406"
},
"status": "Signed",
"signature": {
"r": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c",
"s": "0x47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f14a63da7ce5a1fe",
"recid": 0,
"encoded": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f10000000000000000"
},
"dateRequested": "2023-05-15T20:21:11.576Z",
"dateSigned": "2024-01-10T19:07:40.533Z"
}

Polkadot: Generate Signature

Request body

Property

Type

Description

kind*

String

For Polkadot, always Message

message*

Hex String

The unsigned hex encoded signer payload as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Message",
"message": "0x0403007f87d29a4746b8e59e347c0598ad811a10c3cd8735d49cf96b75973864c8c98b0475000400386d0f0019000000e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423eb3b9c09f232a12c50f40e023a01f0b86d679b84748cc289534d96861ef611c67"
}

200 response example

{
"id": "sig-7lths-cbrl3-xxxxxxxxxxxxxxxx",
"walletId": "wa-3oo6h-s4n5l-xxxxxxxxxxxxxxxx",
"network": "Westend",
"requester": {
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Message",
"message": "0x0403007f87d29a4746b8e59e347c0598ad811a10c3cd8735d49cf96b75973864c8c98b0475000400386d0f0019000000e143f23803ac50e8f6f8e62695d1ce9e4e1d68aa36c1cd2cfd15340213f3423eb3b9c09f232a12c50f40e023a01f0b86d679b84748cc289534d96861ef611c67"
},
"status": "Signed",
"signature": {
"r": "0xb3e424deda8c544cdeb5e70e06b0cc44f7a4fe75378a8939fcd0bddec11d6e85",
"s": "0xbd2d4cf5baf6bfc55f164581e2f5ef15ca3d7965ccca6b33f1190e86692cfc04",
"encoded": "0x00b3e424deda8c544cdeb5e70e06b0cc44f7a4fe75378a8939fcd0bddec11d6e85bd2d4cf5baf6bfc55f164581e2f5ef15ca3d7965ccca6b33f1190e86692cfc04"
},
"dateRequested": "2024-05-09T19:03:27.385Z",
"dateSigned": "2024-05-09T19:03:28.188Z"
}

Typescript Example with polkadot{.js}

First install the polkadot{.js} SDK. You can find the full documentation here: https://polkadot.js.org/docs/

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import { ApiPromise, HttpProvider } from '@polkadot/api'
import { EXTRINSIC_VERSION } from '@polkadot/types/extrinsic/v4/Extrinsic'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const httpProvider = new HttpProvider(process.env.POLKADOT_NODE_URL!)
const api = await ApiPromise.create({
provider: httpProvider,
signer: senderWallet,
noInitWarn: true,
})

const transaction = api.tx.balances.transferKeepAlive('5EwvHZHrKd9WYc3LByzMZW5cmxJt9VMsfYiKg5jCJb8UBfbC', 10000)
const signerPayload: any = transaction.registry.createTypeUnsafe('SignerPayload', [
transaction,
{ version: EXTRINSIC_VERSION },
])

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Message',
message: signerPayload.toRaw().data,
},
})

Solana: Generate Signature

Request body

Property

Type

Description

kind*

String

For Solana, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008001000103b25c8c464080ab2835a166d2b3f13195c2ff3c8f281c7ebe492f0d45d830ff4824a8b38a94b73d2756f2be68655a49706be9b1dc900978984d6eeaf65ab62e900000000000000000000000000000000000000000000000000000000000000000ed589eed2559d935c834cd6d6cbee12970423ad37853618d39e632032aa4c51201020200010c02000000010000000000000000"
}

200 response example

{
"id": "sig-2rv2t-u0cmd-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "SolanaDevnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008001000103b25c8c464080ab2835a166d2b3f13195c2ff3c8f281c7ebe492f0d45d830ff4824a8b38a94b73d2756f2be68655a49706be9b1dc900978984d6eeaf65ab62e900000000000000000000000000000000000000000000000000000000000000000ed589eed2559d935c834cd6d6cbee12970423ad37853618d39e632032aa4c51201020200010c02000000010000000000000000"
},
"status": "Signed",
"signature": {
"r": "0x87e2fafa916877495baed6adb66283fcecd6166c73b1bb5812441045fc52b5ac",
"s": "0x52f5216e39945db8a1fc7a19778813ed30e4cb84787ff9fe7a1e4f1d7976d70f",
"encoded": "0x87e2fafa916877495baed6adb66283fcecd6166c73b1bb5812441045fc52b5ac52f5216e39945db8a1fc7a19778813ed30e4cb84787ff9fe7a1e4f1d7976d70f"
},
"signedData": "0x0187e2fafa916877495baed6adb66283fcecd6166c73b1bb5812441045fc52b5ac52f5216e39945db8a1fc7a19778813ed30e4cb84787ff9fe7a1e4f1d7976d70f8001000103b25c8c464080ab2835a166d2b3f13195c2ff3c8f281c7ebe492f0d45d830ff4824a8b38a94b73d2756f2be68655a49706be9b1dc900978984d6eeaf65ab62e900000000000000000000000000000000000000000000000000000000000000000ed589eed2559d935c834cd6d6cbee12970423ad37853618d39e632032aa4c51201020200010c02000000010000000000000000",
"dateRequested": "2024-01-10T19:45:08.059Z",
"dateSigned": "2024-01-10T19:45:08.285Z"
}

Typescript Example with Solana web3.js

First install the Solana web3.js SDK. You can find the full documentation here: https://docs.solana.com/developing/clients/javascript-api

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import {
clusterApiUrl,
Connection,
PublicKey,
SystemProgram,
TransactionMessage,
VersionedTransaction,
} from '@solana/web3.js'

const walletId = 'wa-6lbfv-9esgj-88s80c0qsih0a393'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const myAddress = new PublicKey(wallet.address)
const toAddress = new PublicKey('3U6stgsD1FmA7o3omUguritCU8iWmUM7Rs6KqAHHxHVZ')

const connection = new Connection(clusterApiUrl('devnet'), 'confirmed')
const latestBlockhash = await connection.getLatestBlockhash()

const message = new TransactionMessage({
payerKey: myAddress,
recentBlockhash: latestBlockhash.blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: myAddress,
toPubkey: toAddress,
lamports: 1n,
}),
],
}).compileToV0Message()
const transaction = new VersionedTransaction(message)

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${Buffer.from(transaction.serialize()).toString('hex')}`,
},
})

Stellar: Generate Signature

Request body

Property

Type

Description

kind*

String

For Stellar, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x0000000500000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de33700000000000001900000000200000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de337000000640013442f00000039000000010000000000000000000000006630fac3000000010000001054657374205472616e73616374696f6e00000001000000000000000100000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de3370000000000000000000000640000000000000001698de33700000040d3c6d585afb419d91e35576327b084515a4e38cf80b1614923b60c09161db46d7624cdc5fcbde7077db82121f421f1d1ab5365c2d949680fe0decbd2c5b7a9080000000000000000"
}

200 response example

{
"id": "sig-54nid-a4qqp-xxxxxxxxxxxxxxxx",
"walletId": "wa-6dh0q-kq130-xxxxxxxxxxxxxxxx",
"network": "StellarTestnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x0000000500000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de33700000000000001900000000200000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de337000000640013442f00000039000000010000000000000000000000006630fac3000000010000001054657374205472616e73616374696f6e00000001000000000000000100000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de3370000000000000000000000640000000000000001698de33700000040d3c6d585afb419d91e35576327b084515a4e38cf80b1614923b60c09161db46d7624cdc5fcbde7077db82121f421f1d1ab5365c2d949680fe0decbd2c5b7a9080000000000000000"
},
"status": "Signed",
"signature": {
"r": "0x42d0aeedc08cf943a8d860eb5e5c93b07a18e438e07992f3113697faae876701",
"s": "0x885fa61a33137c7d5a95a22de2761efa6095ee29cb1fae6f933bcd80f2be1805",
"encoded": "0x42d0aeedc08cf943a8d860eb5e5c93b07a18e438e07992f3113697faae876701885fa61a33137c7d5a95a22de2761efa6095ee29cb1fae6f933bcd80f2be1805"
},
"signedData": "0x0000000500000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de33700000000000001900000000200000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de337000000640013442f00000039000000010000000000000000000000006630fac3000000010000001054657374205472616e73616374696f6e00000001000000000000000100000000d6319d6ad33ba335eb96bf1355a5d930d95f2894067023e15d6046eb698de3370000000000000000000000640000000000000001698de33700000040d3c6d585afb419d91e35576327b084515a4e38cf80b1614923b60c09161db46d7624cdc5fcbde7077db82121f421f1d1ab5365c2d949680fe0decbd2c5b7a9080000000000000001698de3370000004042d0aeedc08cf943a8d860eb5e5c93b07a18e438e07992f3113697faae876701885fa61a33137c7d5a95a22de2761efa6095ee29cb1fae6f933bcd80f2be1805",
"dateRequested": "2024-04-30T14:02:56.936Z",
"dateSigned": "2024-04-30T14:02:57.209Z"
}

Typescript Example with Stellar SDK

First install the Stellar SDK. You can find the full documentation here: https://stellar.github.io/js-stellar-sdk/

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import { Asset, BASE_FEE, Horizon, Networks, Operation, TransactionBuilder } from '@stellar/stellar-sdk'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const provider = new Horizon.Server(process.env.HORIZON_API_URL!)

const account = await provider.loadAccount(senderWallet.address)
const transaction = new TransactionBuilder(account, {
fee: BASE_FEE,
networkPassphrase: Networks.TESTNET,
})
.addOperation(
Operation.payment({
destination: 'GAZWLHTNAOJWW52GZCUJAS5MSXK7LAWCUC5TFOFFVDQ7CDTNFODJ37GB',
asset: Asset.native(),
amount: '1',
})
)
.setTimeout(180)
.build()

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${transaction.toEnvelope().toXDR('hex')}`,
},
})

Tezos: Generate Signature

Request body

Property

Type

Description

kind*

String

For Tezos, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x04c4b1966777a5d83f3f61e17bf64aa6090ddd3413ede4e24316d3334a7836486c0060f4b0700cb1b73bff168a6221c6a033de12953ebc029d82d50a8d02000100008017ed86b1bbb1c6a9399fc47b83fb8a919e013400"
}

200 response example

{
"id": "sig-5fnhg-8u56n-xxxxxxxxxxxxxxxx",
"walletId": "wa-5kqa8-4leor-xxxxxxxxxxxxxxxx",
"network": "TezosGhostnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x04c4b1966777a5d83f3f61e17bf64aa6090ddd3413ede4e24316d3334a7836486c0060f4b0700cb1b73bff168a6221c6a033de12953ebc029d82d50a8d02000100008017ed86b1bbb1c6a9399fc47b83fb8a919e013400"
},
"status": "Signed",
"signature": {
"r": "0x487430064a2449da0fde2e89009f4a0d8270f252bfffbe5ed3ae7239953330bc",
"s": "0x1d98659c776dcfc1e0c12b93a309f23932de021572c41dfdd0b44e10b273830f",
"encoded": "0x487430064a2449da0fde2e89009f4a0d8270f252bfffbe5ed3ae7239953330bc1d98659c776dcfc1e0c12b93a309f23932de021572c41dfdd0b44e10b273830f"
},
"signedData": "0x82e386190d4d05ffe57db31467a83ccd6308f4eee59dff9319f2c60cf8a1f3db6c0060f4b0700cb1b73bff168a6221c6a033de12953ebc029d82d50a8d02000100008017ed86b1bbb1c6a9399fc47b83fb8a919e013400487430064a2449da0fde2e89009f4a0d8270f252bfffbe5ed3ae7239953330bc1d98659c776dcfc1e0c12b93a309f23932de021572c41dfdd0b44e10b273830f",
"dateRequested": "2024-01-10T20:06:08.607Z",
"dateSigned": "2024-01-10T20:06:08.804Z"
}

Typescript Example with Taquito

First install the Taquito SDK. You can find the full documentation here: https://taquito.io/docs/quick_start/

Taquito is a little special in that it requires a signer to forge an operation. In fact, we only need the signer to return the wallet address and the (encoded) public key. We'll initialize a Taquito RPC instance using our fake signer and a local forger (see below). After forging the operation, we can sign via the Dfns TypeScript SDK.

import { RpcClient } from '@taquito/rpc'
import { Signer, TezosToolkit } from '@taquito/taquito'
import { LocalForger } from '@taquito/local-forging'
import { Prefix, b58cencode, prefix } from '@taquito/utils'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

// Tezos requires a signer to forge a transaction. When forging, we only
// need 'publicKeyHash' (address) and 'publicKey' (encoded)
class TezosToolkitSigner implements Signer {
sign(): Promise<{
bytes: string
sig: string
prefixSig: string
sbytes: string
}> {
throw new Error('Method not implemented.')
}
async publicKey(): Promise<string> {
const prefix = wallet.signingKey.scheme === 'EdDSA' ? Prefix.EDPK : Prefix.SPPK
return b58cencode(wallet.signingKey.publicKey, prefix)
}

async publicKeyHash(): Promise<string> {
return wallet.address
}

secretKey(): Promise<string | undefined> {
throw new Error('Method not implemented.')
}
}

const client = new RpcClient('TEZOS_NODE_URL')
const Tezos = new TezosToolkit(client)
const forger = new LocalForger()

Tezos.setForgerProvider(forger)
Tezos.setSignerProvider(new TezosToolkitSigner())

const receiver = 'tz1XKKrD4NLRhBK4PFxQ4XvH2KXZ6J389N1Z'

// estimate fees
const estimate = await Tezos.estimate.transfer({
source: wallet.address,
to: receiver,
amount: 1,
})

const prepared = await Tezos.prepare.transaction({
source: wallet.address,
to: receiver,
amount: 1,
fee: estimate.suggestedFeeMutez,
gasLimit: estimate.gasLimit,
storageLimit: estimate.storageLimit,
})

const forgeable = await Tezos.prepare.toForge(prepared)
const forgedBytes = await forger.forge(forgeable)

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${forgedBytes}`,
},
})

TRON: Generate Signature

Request body

Property

Type

Description

kind*

String

For Tron, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x0a83010a0228222208b142ad939b228d784090a7eaa9cf315a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15419d31b91d72b58d7c8c02a7124410e168989f372d12154102a69d5d85c05864dc6fd74f57db3fa37aff7b94180170b0d2e6a9cf31"
}

200 response example

{
"id": "sig-19u01-g60tf-xxxxxxxxxxxxxxxx",
"walletId": "wa-174tk-m918i-xxxxxxxxxxxxxxxx",
"network": "TronNile",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x0a83010a0228222208b142ad939b228d784090a7eaa9cf315a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15419d31b91d72b58d7c8c02a7124410e168989f372d12154102a69d5d85c05864dc6fd74f57db3fa37aff7b94180170b0d2e6a9cf31"
},
"status": "Signed",
"signature": {
"r": "0xa7c36732ea21596a533ad44e1d2f5eff72ae3d178225a0cdb9869ff3954a3898",
"s": "0x37b7f22f119801ce5fe1723f3a397254ba8f968ba5ad63e66404caf750666968",
"recid": 1,
"encoded": "0xa7c36732ea21596a533ad44e1d2f5eff72ae3d178225a0cdb9869ff3954a389837b7f22f119801ce5fe1723f3a397254ba8f968ba5ad63e66404caf7506669681c"
},
"signedData": "0x0a83010a0227f52208511ce7ed0476508040c8d9e1a9cf315a65080112610a2d747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e5472616e73666572436f6e747261637412300a15419d31b91d72b58d7c8c02a7124410e168989f372d12154102a69d5d85c05864dc6fd74f57db3fa37aff7b94180170e884dea9cf311241a7c36732ea21596a533ad44e1d2f5eff72ae3d178225a0cdb9869ff3954a389837b7f22f119801ce5fe1723f3a397254ba8f968ba5ad63e66404caf7506669681c",
"dateRequested": "2024-01-10T21:13:38.186Z",
"dateSigned": "2024-01-10T21:13:38.348Z"
}

Typescript Example with TronWeb

First install Tronweb. You can find the full documentation here: https://tronweb.network/docu/docs/intro/

Tron requires the transaction to be serialized using the protobuf format before it can be broadcast. As it's not trivial, you can use the functions exposed in Tronweb to generate the transaction in the right format (see below) and then sign via the Dfns TypeScript SDK:

const TronWeb = require('tronweb')

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const transaction = await tronWeb.transactionBuilder.sendTrx('TADDx31pdCFfp3XrYxp6fQGbRxriYFLTrx', 1000, wallet.address)

const txPb = TronWeb.utils.transaction.txJsonToPb(transaction)

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${TronWeb.utils.bytes.byteArray2hexStr(txPb.serializeBinary())}`,
},
})

TON: Generate Signature

TON chains support the following signature kinds:

  • Message: Generates a signature for a signing message.

  • Hash: Generates the signature for the hash digest of the original message.

Message Signature

Generates a signature from a serialized signing message BoC.

Property

Type

Description

kind*

String

Message

message*

Hex String

The serialized signing message BoC

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Message",
"message": "0xb5ee9c7241010201004400011c29a9a317671ba91000000004000301006242000b3fa8f8f4c8abf5f1086d9d8ca76c23ac7186a03cd4142b77428237abb8bfb7880800000000000000000000000000bc0d3854"
}

200 response example

{
"id": "sig-19u01-g60tf-xxxxxxxxxxxxxxxx",
"walletId": "wa-174tk-m918i-xxxxxxxxxxxxxxxx",
"network": "TonTestnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Message",
"transaction": "0xb5ee9c7241010201004400011c29a9a317671ba91000000004000301006242000b3fa8f8f4c8abf5f1086d9d8ca76c23ac7186a03cd4142b77428237abb8bfb7880800000000000000000000000000bc0d3854"
},
"status": "Signed",
"signature": {
"r": "0xb1cbcdcfefce82ba35c3b7ed352b77876c917528e2f1b668599847860f2f02c2",
"s": "0xc26389dca075e706973526195a70282f7c0dc63b94ac1aed8fe85f2116eb3202",
"encoded": "0xb1cbcdcfefce82ba35c3b7ed352b77876c917528e2f1b668599847860f2f02c2c26389dca075e706973526195a70282f7c0dc63b94ac1aed8fe85f2116eb3202"
},
"dateRequested": "2024-01-10T21:13:38.186Z",
"dateSigned": "2024-01-10T21:13:38.348Z"
}

Typescript Example with ton-core

First install ton-core. You can find the full documentation here: https://github.com/ton-org/ton

Ton requires a specific message format when interacting with the network. We need to create a signing message payload BoC. Then, we can sign the BoC via the Dfns TypeScript SDK:

import { beginCell, internal, SendMode, storeMessageRelaxed, TonClient, WalletContractV4 } from '@ton/ton'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const client = new TonClient({ endpoint })

const contract = client.open(
WalletContractV4.create({
workchain: 0,
publicKey: Buffer.from(wallet.signingKey.publicKey, 'hex'),
})
)

const seqno = await opened.getSeqno()

const builder = beginCell().storeUint(contract.walletId, 32)
if (seqno === 0) {
for (let i = 0; i < 32; i++) {
builder.storeBit(1)
}
} else {
builder.storeUint(Math.floor(Date.now() / 1e3) + 60, 32)
}

builder.storeUint(seqno, 32)
builder.storeUint(0, 8)
builder.storeUint(SendMode.PAY_GAS_SEPARATELY, 8)

const message = internal({
value: '1',
to: '0QDXET3_xkWbJwXv16hU402QY3hS3cCelF5Ax3cvUpEbzG5A',
body: 'Dfns SDK Example',
})

const cell = builder.storeRef(beginCell().store(storeMessageRelaxed(message))).endCell()

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Message',
message: `0x${cell.toBoc().toString('hex')}`,
},
})

Hash Signature

Generates the signature for the hash digest of the original message.

Request body

Property

Type

Description

kind*

String

Hash

hash*

String

The hash digest in hex.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Hash",
"hash": "0x031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406"
}

200 response example

{
"id": "sig-19u01-g60tf-xxxxxxxxxxxxxxxx",
"walletId": "wa-174tk-m918i-xxxxxxxxxxxxxxxx",
"network": "TonTestnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Hash",
"hash": "031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406"
},
"status": "Signed",
"signature": {
"r": "0xb1cbcdcfefce82ba35c3b7ed352b77876c917528e2f1b668599847860f2f02c2",
"s": "0xc26389dca075e706973526195a70282f7c0dc63b94ac1aed8fe85f2116eb3202",
"encoded": "0xb1cbcdcfefce82ba35c3b7ed352b77876c917528e2f1b668599847860f2f02c2c26389dca075e706973526195a70282f7c0dc63b94ac1aed8fe85f2116eb3202"
},
"dateRequested": "2024-01-10T21:13:38.186Z",
"dateSigned": "2024-01-10T21:13:38.348Z"
}

XRP Ledger (aka Ripple): Generate Signature

Request body

Property

Type

Description

kind*

String

For XRP Ledger, always Transaction

transaction*

Hex String

The unsigned hex encoded transaction as shown below

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Transaction",
"transaction": "0x120000220000000024029a62a82e0001e240201b02a6243661400000000000000168400000000000000c8114860184b4f4c6cc17ae9c2a77cfcd328b43ec2aac8314543aba55a3bede29c5d512ff0cb17db626b9ed9a"
}

200 response example

{
"id": "sig-60es5-5sc68-xxxxxxxxxxxxxxxx",
"walletId": "wa-4ih27-hei2f-xxxxxxxxxxxxxxxx",
"network": "RippleTestnet",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-341e6-12nj6-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Transaction",
"transaction": "0x120000220000000024029a62a82e0001e240201b02a6243661400000000000000168400000000000000c8114860184b4f4c6cc17ae9c2a77cfcd328b43ec2aac8314543aba55a3bede29c5d512ff0cb17db626b9ed9a"
},
"status": "Signed",
"signature": {
"r": "0x62a635aa543697406c1b15e6ec33b8bba1c62ab741d255ad822fc6f45d6c2881",
"s": "0x24737ad61088a13134a75556707f7f73fa830991a812810daeacf9dffbe92db0",
"recid": 1,
"encoded": "0x3044022062a635aa543697406c1b15e6ec33b8bba1c62ab741d255ad822fc6f45d6c2881022024737ad61088a13134a75556707f7f73fa830991a812810daeacf9dffbe92db0"
},
"signedData": "0x120000220000000024029a62a82e0001e240201b02a6242361400000000000000168400000000000000c732102790b1b6ab9bc9d816dda4d2d4528996a2c78ad90e176f87d48c6f5333989dbc374463044022062a635aa543697406c1b15e6ec33b8bba1c62ab741d255ad822fc6f45d6c2881022024737ad61088a13134a75556707f7f73fa830991a812810daeacf9dffbe92db08114860184b4f4c6cc17ae9c2a77cfcd328b43ec2aac8314543aba55a3bede29c5d512ff0cb17db626b9ed9a",
"dateRequested": "2024-01-10T21:19:08.579Z",
"dateSigned": "2024-01-10T21:19:08.760Z"
}

Typescript Example with xrpl.js

First install xrpl.js. You can find the full documentation here: https://js.xrpl.org/

Here a code sample to generate a signature via the Dfns TypeScript SDK:

import { Client, encode } from 'xrpl'

const walletId = 'wa-6lbfv-9esgj-xxxxxxxxxxxxxxxx'
const wallet = await dfnsClient.wallets.getWallet({ walletId })

const client = new Client(RIPPLE_NODE_URL)
await client.connect()

const transaction = await client.autofill({
TransactionType: 'Payment',
Account: wallet.address,
Destination: 'rBYtCQKxGTfFuob3hxSc8pEYddetT9CdDZ',
Amount: '1',
})

const res = await dfnsClient.wallets.generateSignature({
walletId,
body: {
kind: 'Transaction',
transaction: `0x${encode(transaction).toLowerCase()}`,
},
})

Pseudo Networks (All other chains): Generate Signature

Dfns is compatible with any blockchain that supports our underlying MPC cryptographic schemes and elliptical curves:

  • ECDSA over secp256k1

  • ECDSA over Stark curve

  • EdDSA over Ed25519

You can use Generate Signature to interact with any chain supporting these schemes by using Pseudo Network enumerated types when you create a wallet.

Hash Signing Support - All Schemes

All cryptographic scheme support hash signing. Note ECDSA with secp256k1 or Stark curve only support this kind. Use the target chain's native SDK to hash your message before sending to Dfns.

Property

Type

Description

kind*

String

Hash

hash*

Hex String

The hash digest in hex.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Hash",
"hash": "0x031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406"
}

200 response example

{
"id": "sig-2ouaj-f4nq6-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "KeyECDSA",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Hash",
"hash": "0x031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406"
},
"status": "Signed",
"signature": {
"r": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c",
"s": "0x47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f14a63da7ce5a1fe",
"recid": 0
},
"dateRequested": "2023-05-15T20:21:11.576Z",
"dateSigned": "2024-01-10T19:07:40.533Z"
}

EdDSA Message Signing

In addition to the Hash method shown above, EdDSA also supports signing Messages as shown below. For message encoding standards, see the documentation of the chain you are targeting.

Property

Type

Description

kind*

Required

Message

message*

Required

The original message hex encoded.

externalId

(Optional) String

A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here)

Sample request body

{
"kind": "Message",
"message": "0x01000507a824baef8cad745bb58148551728d245d6fc21679d1b8f3bbf6abed957f614719dca9b4fcc2b6a68aab9ef37b4db8dc5e99d2d803b577cc61c042453ddd525a6d215d4421860fc0e4a48255b2a6781a494e7ee3f055eeeda2233b590a07b6a2806a1d8179137542a983437bdfe2a7ab2557f535c8a78722b68a49dc00000000006a1d817a502050b680791e6ce6db88e1e5b7150f61fc6790a4eb4d10000000006a7d51718c774c928566398691d5eb68b5eb8a39b4b6d5c73555b210000000006a7d517193584d0feed9bb3431d13206be544281b57b8566cc5375ff40000001abbca65c30117367204561151b7660a672b5fc9fe3d2780d130ea30be604eea0103060102050604000402000000"
}

200 response example

{
"id": "sig-2rv2t-u0cmd-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "KeyEdDSA",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Message",
"message": "0x01000507a824baef8cad745bb58148551728d245d6fc21679d1b8f3bbf6abed957f614719dca9b4fcc2b6a68aab9ef37b4db8dc5e99d2d803b577cc61c042453ddd525a6d215d4421860fc0e4a48255b2a6781a494e7ee3f055eeeda2233b590a07b6a2806a1d8179137542a983437bdfe2a7ab2557f535c8a78722b68a49dc00000000006a1d817a502050b680791e6ce6db88e1e5b7150f61fc6790a4eb4d10000000006a7d51718c774c928566398691d5eb68b5eb8a39b4b6d5c73555b210000000006a7d517193584d0feed9bb3431d13206be544281b57b8566cc5375ff40000001abbca65c30117367204561151b7660a672b5fc9fe3d2780d130ea30be604eea0103060102050604000402000000"
},
"status": "Signed",
"signature": {
"r": "0x05e365d4304eaa78516eb309bff91f8c12e5445a431e3f2428239678d0150c6c",
"s": "0x47e0765c439fb42d57767910865d240964b7b09f2b2f74d8f14a63da7ce5a1fe"
},
"dateRequested": "2023-05-15T20:21:11.576Z",
"dateSigned": "2024-01-10T19:07:40.533Z"
}

Get Wallet Signature Request by ID

GET /wallets/{walletId}/signatures/{signatureId}

Get a signature request of a wallet.

Required Permissions

Name

Conditions

Wallets:ReadSignature

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex. wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

signatureId

Unique identifier of the signature request. ex. sg-4tcfd-enph7-xxxxxxxxxxxxxxxx

Response

Response example

{
"id": "sig-4tcfd-enph7-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Eip712",
"types": {
"Person": [
{
"name": "name",
"type": "string"
},
{
"name": "wallet",
"type": "address"
}
],
"Mail": [
{
"name": "from",
"type": "Person"
},
{
"name": "to",
"type": "Person"
},
{
"name": "contents",
"type": "string"
}
]
},
"domain": {
"name": "Ether Mail",
"version": "1",
"chainId": 1,
"verifyingContract": "0x1b352de7a926ebd1bf52194dab487c2cb0793a9b",
"salt": "0xf2d857f4a3edcb9b78b4d503bfe733db1e3f6cdc2b7971ee739626c97e86a558"
},
"message": {
"from": {
"name": "Chris",
"wallet": "0x00e3495cf6af59008f22ffaf32d4c92ac33dac47"
},
"to": {
"name": "Bob",
"wallet": "0xcc0ee1a1c5e788b61916c8f1c96c960f9a9d3db7"
},
"contents": "Hello, Bob!"
}
},
"status": "Signed",
"signature": {
"r": "0xb23c2cfb6d409f5a55ced08f89ae70f3fe89403a5ba907c367545499874f1c7f",
"s": "0x49992f242a21ae0692c24b43393336744ddc08459d936b6a70542d79df4f66f0",
"recid": 1,
"encoded": "0xb23c2cfb6d409f5a55ced08f89ae70f3fe89403a5ba907c367545499874f1c7f49992f242a21ae0692c24b43393336744ddc08459d936b6a70542d79df4f66f01c"
},
"dateRequested": "2023-05-15T19:26:18.145Z",
"dateSigned": "2023-05-15T19:26:20.517Z",
"approvalId": "ap-...", // defined only if an approval process was triggered as the result of a policy ("status" will be "Pending" then)
}

List Wallet Signature Requests

GET /wallets/{walletId}/signatures?paginationToken={token}

List signature requests of a wallet.

Required Permissions

Name

Conditions

Wallets:ReadSignature

Always Required

Parameters

Path parameters

Path parameter

Description

walletId

Unique identifier of the Wallet. ex.wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx

Query parameters

Query string parameter

Required/Optional

Description

Type

limit

Optional

Maximum number of items to return. Default to 50.

Number

paginationToken

Optional

Opaque token used to retrieve the next page. Returned as nextPageToken from the previous request.

String

Response

Response example

{
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"items": [
{
"id": "sig-2ouaj-f4nq6-xxxxxxxxxxxxxxxx",
"walletId": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"network": "EthereumSepolia",
"requester": {
"userId": "us-3v1ag-v6b36-xxxxxxxxxxxxxxxx",
"tokenId": "to-7mkkj-c831n-xxxxxxxxxxxxxxxx",
"appId": "ap-24vva-92s32-xxxxxxxxxxxxxxxx"
},
"requestBody": {
"kind": "Hash",
"hash": "031edd7d41651593c5fe5c006fa5752b37fddff7bc4e843aa6af0c950f4b9406"
},
"status": "Confirmed",
"signature": {
"r": "0xb23c2cfb6d409f5a55ced08f89ae70f3fe89403a5ba907c367545499874f1c7f",
"s": "0x49992f242a21ae0692c24b43393336744ddc08459d936b6a70542d79df4f66f0",
"recid": 1,
"encoded": "0xb23c2cfb6d409f5a55ced08f89ae70f3fe89403a5ba907c367545499874f1c7f49992f242a21ae0692c24b43393336744ddc08459d936b6a70542d79df4f66f01c"
},
"txHash": "0xf2e2ff61460ec26b0355c0186f17d9263c616d045e7ec3d2b13c18af80c856df",
"dateRequested": "2023-05-15T20:21:11.576Z",
"dateSigned": "2023-05-15T20:21:16.564Z",
"dateConfirmed": "2023-05-15T20:28:36.000Z"
},
...
],
"nextPageToken": "WszQXoENUIYyoBQjJm4DE6QhCk2sB7WAh9kykUMaTQcD25SToKbuXkgf3td8ZYb2LrtopPLo35u407gwwA1Sug=="
}

Advanced Wallet APIs

The following APIs are contractually limited due to their impact on the security of private keys. Please contract your sales representative for additional information.

Import Wallet

POST /wallets/import

  • This endpoint is not enabled by default. Contact Dfns to have it activated.

  • User action signature required. See User Action Signing for more information.

  • Request headers required. See Request Headers for more information.

  • Authentication required. See Authentication Headers for more information.

Dfns secures private keys by generating them as MPC key shares in our decentralized key management network. This happens by default when you create a wallet.

In some circumstances, however, you may need to import an existing wallet (an existing private key) into Dfns infrastructure, instead of creating a brand new wallet with Dfns and transfer funds to it. As an example, you might want to keep an existing wallet if its address is tied to a smart contract which you don't want to re-deploy.

In such a case, Dfns exposes this wallet import API endpoint, which can be used in conjunction with our import SDK. Note this is intended to be used only to migrate wallets when first onboarding onto the Dfns platform.

Dfns can not guarantee the security of imported wallets, as we have no way to control who had access to the private key prior to import. For this reason, this feature is restricted to Enterprise customers who have signed a contractual addendum limiting our liability for imported keys. Please contact your sales representative for more information.

Required Permissions

Name

Conditions

Signers:ListSigners

Always Required

Wallets:Import

Always Required

Wallet Import Flow

The wallet private key which you need to import will never be transmitted to Dfns API in one piece or in the clear (un-encrypted). The process is:

  1. On your side (client-side), you call our GET /signers endpoint to get some information about your Signing Cluster. Your Signing Cluster is the network of nodes (also referred as "signers") the wallet key shares will be imported to. This will provide you with useful information for import (signer IDs, import encryption keys, etc.). This step corresponds to this line in our SDK wallet import example.

  2. With the help of our import SDK libraries, the private key is MPC-sharded on the client side, and each key share is then get encrypted with the corresponding signer encryption key it will get imported to. This step corresponds to this line in our SDK wallet import example.

  3. You then call the Wallet Import endpoint, providing the API with each encrypted key share. This step corresponds to this line in our SDK wallet import example.

  4. Each of those encrypted key shares is transmitted to the corresponding secure node in the Signing Cluster. Each node will then be able to securely decrypt its key share, validate that it is correct, secure it and store it the same way as any wallet in Dfns infrastructure.

Request body

Property

Type - Required/Optional

Description

network

String - Required

Network enum for the wallet (See Supported Networks + Pseudo Network for possible values)

name

String - Required

A name for the wallet

protocol

String - Required

Always CGGMP21 (only protocol supported for import currently)

curve

String - Required

Always secp256k1 (only curve supported for import currently)

minSigners

Integer - Required

Always 3. Min number of signers to complete a signature (TSS threshold).

encryptedKeyShares

Object Array - Required

An array of objects containing the encrypted keyshares. See format below.

encryptedKeyShares

Property

Type - Required/Optional

Description

signerId

String - Required

ID of the signer returned from GET /signers

encryptedKeyShare

String - Required

The key share encrypted with the private key created for the import operation

Example JSON

{
"network": "EthereumSepolia",
"name": "My Imported Wallet",
"protocol": "CGGMP21",
"curve": "secp256k1",
"minSigners": 3,
"encryptedKeyShares": [
{
"signerId": "EX5PdJFcutVTJCgAcSGGGy264JwnrOLLyrZIqMHG67I=",
"encryptedKeyShare": "ilp3GeoJ7HZZx6+iPuA7K2uQkTzle1WUiGppwB45GWpdLu7eyVO5g2aUOIntHY8YMi74wyLl8CVr2gZd2K8+JKP7vArBg3wPkZaHaI3YnTEadPz3wq9jjbIlV7AxKaxot7pWAsjjOupqDH6hkELrNwrbyBOq0LablGykHX0ZOGYbvPgGl3ueUfp5EIaDsYHgkPCivvqABgAzTqlLDPdn4BsZmDgz+4DmliPytGhzZFEMmFROzYCPuW+NP+t6cK4LVY7PrvN4/Pvt/JJE6g5tlY24ErbVQpxjCwaFc+Hxql+fhPCocMWVxkPtCoQ7Rk8Ajr72/8sAKFnKYDh10tOzE+cLJtqPmuHLMx2bH+pHwgxDjmkpIuGcLI1vyrIHH0Vv6rjzI/ZvS6Y3zr0uwgsVEtgHuip0tdN8KY4hMvYXPKo3dWwG1vzfhjynoQ4m0kAyP89btI8VqYPKF61xCKf6dhg8J5TZ2HtoHbG3l33HMsn04gd+1FCTPXIcXlmZCqNQE4r1hOkPlg4DbUBOKGq4mTSUvTVjA+HV2GB+CUMQk7wQ6tKgCGZ5+8gSvDhrmFbW7cB8tJayeDJq/KmNBqCyYcUOg4g0gOZjcD8yf2ZNHiVXM973BDjZXN+XeJMrQ9AfVkmzGq7JB6IJJgaYVhp3T0nQLOTf926P6kWXmabct/U6ZlC+SzKL04wRUr3Qx9YxJYYV0DkzZ9dOwogQgffz0V+zvs3D6/oUYqbplVZcz31lERn5Ej7VuSKnlZnbjwMQNcON8nVJjcSaa0XGUKLBProwNz6o3OqamZU7ZxmqRZXKsOjnBh20I8i1lXPm2Pvt1EoteweGKSbHeXJEVhpI3dbh8mxN14AbIMfg60zxrYbwYqBW4qCrY82F0biyCIqOnQHwPRQ0U7CpNM1p93sFvx4TgIPyn6dOmzEVWtqiv4mEQY4ySa7FzrM2E+osPoZoM6U/SJ+ct3stAdR5Vtt0swbbGLkVApctClWRJzDNcm4ttQj537UOYFM5qVvpcsVBUN7G/kDfrlxs8JAqG0JAsQho/G2TMBgRFq60dQGIjhxqMlwiQqD3NTnI/e0Zb0o+zJS113S0XYZhlQAQvmmoXsFivs7AQJOR4ZrEc4buHMuZ39cYrRIvEYQc9vw8hlC7HQX0Up4zoYjpQENnWIzKDmhKvYFsVwKbaHPM5UKFY8MyzjuYQAGfr0rx4uXJd1h/45SMtdaEUVx1ODZDpLLtw4u7+Rq72lQUD3QBqr3vEK/uzb1vGvvfuJToC/sQ3bwewYCwANOcx6Sj1E6txVroAtrm1uF/jAjXwc3LZnNpCwlIKJHrQfN3Pj0ityI2yP4W"
},
{
"signerId": "KaGnB8iWVpRKBRh+/sAJ0gz1cAZtjhHPufGRgkOXENo=",
"encryptedKeyShare": "LtqCpResE4Nqefa84ue6xKEvf2tuM6hF7+tFI/yN5FelLH/wkAiH+y7g1/1cCdHX+dJzgb7AttBf1SSjVxTMUni2tSBACgR0zkOv922ykEr1lExVOzBVqi6ojfvm79XemrUdvA3z2SReR/unzkm0EoBkOtircv9w/qqddV0RNLL08oEnqGRIsBY1HdLZVHHU/3eY6CUqI+JFQKXmfSutjfGPkjGJpZrtjEo9zqK5YgTxpxTuiJ5UvLiZggh8bKc87Lvk6y/rTYbCFW3eA92og0n/Ac2aGEIIb9XEDetPnFukcmLxF+tQpzHM40Q6/ksAiauSWd0FGwBh8h0m4l7ilC4aQrM3NduTGKQg9sQltuSXk8Re85VLJv0rFQ3K6lcrsPLDq5cbFvH0QhZ6/yTz0YRDQmw5UWkv0T5cYWTpSU84mTusZGAu0IljXrWdlf/8frtPlALzRl1INEOFZ4om1L/0PeXAjSzLYoGPc/sxtRqXdtId8ViCwApT+P9yOTKHQ0rs/Yon+8ZUaEk+jyb0+jYmNcCMg/2bRxy6YoaFfcoV2BwIe/F30dqKzVn4a57iQIZQnKKtY+yJgzaDPKhXJxydUQkr/oRJjK1HFaIlVnYJj9sBVdybBCGNRKE3T2SAHkgBh5x/Avjzamz1h2o8suM1qmqcjI6/L9z335yD+MQdI/vKhs2jAkOQLMxBrPyeJsUMMQiX/jG9FHme6aBiCmNKttyvZFRiYCUPG+XTpfjhX1VIiIrxt4ggFbARADd8hiWIloaFeD1AsFZftd1S/OCWYZuXbWe6bUJQ9wwdGtP8N1tDy6L/U0ObblxFPTRPSkaG3z53clzn7J2WlhlT2B8OnnBntiugvSX2+IuCgN3Hg1eRv9wKD3PVZU4P1ydF+GBPRTvRQLh3SZkMZZNK092dRu05w3jnw+edvBze86BeGYwpSi1isuJY2eIxIWGzhMhED6AdP5+zwq+WkqzpD6iJlup9DwP5CQ0N1n9MsF40E77f4hPkWBbKrkX+cqNgCSCfDgogiq8PK6UWVgumwK488YSUlEUS2Sy1nJ3ZFOXsOOi7IJ1sV+iy4/5a0Hp4beFvK5TRnq+xH9QwYaxnPO6hZlI5n5NvFp8orjVD4jF74MtEX7+I6lvFCSzI19VbK1CNSZhItv+dXk9TGJzbpSUwC3q9JsRmwOv0B1f9oexCmB05kKx22LDLCneT4ZReYDOSnJrLl4YRFwDANrBRdINla+5WgijOx+EWhkISmvt+EF+eOk3S08MjR8UQAXH/hmG0nhmR6uL5gk/ncaRfArEmZmORyqKzJDrPMcyOSL6mhH2eJnYKsqp+SqxNr0vR"
},
{
"signerId": "ZokM6nUhGXHYhtQYE/NTeBEz5udvx13Ympcd1raQ4Fc=",
"encryptedKeyShare": "BFDFlHMCoeVQv9/an2GvzJagri6CGscPWdF24jbKvuwSupRcjx/F3UYg1d/Z/aeHcI+lsxNFRnaimFNRm/JuAWOH1lWEgwaBui0NJXWH+QdTyMH8r+/EHuSQzBNNG4SJ4OAFmrG2YsjlbhZn3bGe9tud50IDhr1X56uhyXL1PS+LHZ5q/saVbljtlQiilQtEphpMeR/spNVHfhRcCamYOt/983qFrcapxY3aFVjEfzt7EGsJxYBV6GDGL4u1juqGne0KEz+nL7HYmofRUOUGQqxsr9tjXOQHD4t2ksCKjzWy2NFcXI4GwSVmk9o8u3xca9RdiWuqRtevmxRGf62NtY8SHbV/vsuhlvqyYtcsjYcU/AKGptTATmPdaF39DvQoVVgwhsmH1OhNb8Tuwd7+XWGXphgO4GbWLmJDMV2pG4CWciqukXaobxrspirzUlqP7jr7GiYpD/4zXZYAL3fFeMOMOm0MG/zmhH4PL++PTPEmP678VPNJKF51EG27VLrZIwHNXpU09v5C8mF0V6GZGU2a1OFPzxX0u1Buj3/f5aTpblBAKLOZBMgAM2DV1ug/ecyELtre5Vz39Qski67i6i5g+rpoCAO0HGS7xYsJaO8PeDssxBwiLQNTj9EcfyaGA2AtMHBc3IWBKWx2h3o/W6cGnKDMxV8W0bWu60qU8HLzFm2IyYzlL+IUSThMEPKndOdwWW3JJEl5ucUGDQc/r7ruqawNoCT0EIkIH/J6jr2WlKm0yfLGgDywmhCme+nEaX0Z1VtBCup4rwm05any9iw71kVKZ8CnAKmqWfw9VOLG1VoQ1NU5SkrkRlct4cacJS2/rUUBHmjfGfTEnF8WtMWynNZIk8eQpDZL9sRWDfFLpXS5F0ltTvjuja6PRJT1lzwF2/ABf1Pvii6eMk50+YgSqq3x9jcgZeGB6bfcnOESfDQ1efpMOuNYI/qc8x8aQF2PRnxsLLUWs4SKvKEGuOVyRKq6/cz3leNgl+ghkaxBwRSnuFKrxt0wRbgaoZlMol3pCwV3XOmlp5i1j+pkgBFNPPfSKxRa/lfo5jmMKuBG7BSc5G6b+XeNfrCDipQMrCqGJIUhhlWcFb01DZsa3a7mTezifQ7QHzYRKPiQsQPD5X6WRgKQkynsSbuyrwZWBa/rbxYRu5McmfE4fSwGg/JyHjP0t4H6rtfNTSViqMfLyGkERI9jyVpymLluWdyR0uoAZJz3nH6+tu/QVqCYZMwBDjAHpWkaNUMMR2iHo8TW9zHY1LqcP5wUM4Osc8mMjLQ9NsAa4Zl7fFnOe3G+Az83TGit72cRfHlgD9Uhnr2c+AcRiO/zQYR5QazLwRJZ"
},
{
"signerId": "lGcHWQmdLtJ+4S+RIBFq704/Nox2bugUctVeLL0wPW8=",
"encryptedKeyShare": "JH7LsR8U92fYjbeUWIuLkJ7Q2yH5X+eQKa6tpk8g/gPkGbgG4JzpyALHK148Xbhr7HN1trQJWhl57NNJnj9UVLxrD0AQ7+23U4Pcl5N9eshva9Npg7ZRI9/PvIfyHzUFzMnsJlk8CzY2O8PyXKObomx4PyTwOUzOUncb3OjHw4aiXt/8DvhwVYRUkuMvvLw6O4yhia6CpD4JGj0p1WtK89UL0981uAEJe76VSQQZwDhpy1UP/aW2/Leej7zj0DVQfNY6YtoTMRjcg5QLeKIOhtf/pDHlos7KWvtjj11pikiISQrdBscMi41PRTv2yJm+SZUoWOrkQNhfm8mOOTLEuH1SvbkJL0mNbSHDSdEWkOJSvx4I/czY97ptwd1sadHVNMG3SNAa/ZRjuWqdOgKgfmSocHZT2SfvnlaZ5EMGW2RK0cqlnqusSENHPHs0QhERD8fpTouER+TJzvIlNVHe0e/PH42muq6aQ4VAQVP4wsVvxlBA53aSMzae9YAKtBPCqfZeXkItdcNmEMdmxQ0/1wm44hswRjieTqqYdvvRuHH2a3ZXlk3KXnlFlBZ3Ve02HSmK4a7/DwrTMmDm8GkdZ0qx2hSBJHiitobqm3wLCy8i6URSkK5oluth8ZTW6vcm9Y230ILiZzvm13jVzPHHl+xuTEUw9AC3lgelapP+4sf2ouYKR1UxKCesnLBuMfRvhlkCwgVuoqbYL/EmnTAw8kXNleQLsQ8jy7F91mGv3FFpAhPEoGoFymNVttmczUjFID+/8k/JdKpxDGC3S+lolKduGgoqLA794WuYkYIlIGU+hX4WHJmGiPSHIATsT/y1pbqYpV1+eYMBJsFRAXP+K/kPX2encKpSCHrLePN0zba9ayQZdMR+bsNHcKGPH94HNtQ4UjziJ9Qfsm+RfwzqgvOzdovKw1qt0NoRHicwFhdx3aQEsSZjmVTL0RmWm89aOvjAiboYlgrEHvuc1S6aySk/5mU58dxMwLtAyyJj1xGm3e9QlsZtD+28uRnbjtRa/mCtQMLv0QLu0Q1wJEPby+FhYX5921Y2h2dz37d3ArOSasuUrY/74sCPuu/olkEFrgyueIPM99IvR1PQbrz57NycZ5HVGuxPyluw82HoDOqKH7h2gKwLV4VNjTRm4IPb0hM/1Yckemx1BXAycD2VNrNbGpDWeYVbDp6OfJqVIFhjiriA6oYITRIDpZCmfGzCDVe9sc9VCeCKIvUu8v6VZg60NoKRfbvAdjERQtLH1KH8fsaUM2zuKojpOAC9OTLDrlnYh69wKZLaBr6t+XPbAjc61AaArNBrNLlsVr7PkD7BtOCIkn19+084YwyXMCFZ"
},
{
"signerId": "9R4OQb12f8PrEQwFmwZ58ZsNHs6EcGQPWF3fSzhXbVk=",
"encryptedKeyShare": "R9p9N+nXc24eq8osgI2KAQq8OeFXk3OLAxH30oieUfgLEFPcF81eZ89XSKS65axBK6U6DqlZhVW1u2adigJSaVYqHaqDT0xycFL+FCX9Mdd9MgNCoNUorkog7EfYK+It44RZTPP3A8X7CWIsl/GqCX1jH9DFKTYapbbfRsxKr50PyYVyQ4qNH5SypGhtXe10poclbRgYbsroRfclDoCZCaBbkCuSIQvTSb/V2pskv/nw2kbzbGp1WC3POaO0gMHzUnEFc+Zc8kI4XcnsviG2qsdw6GoTzVjNpRSEJf9jpL+DoCplmNufOMKyDqEDwWdgiQwx/Y4ZW3F3tDRZ694lAU4S71ACN3+MwfVy46WJHMW+E6x/OTXvVJUuAAHL4b3C8NcbQS4Z7CP51B6rX6Hl50yUZl6Xev1G2WFrYWLzc02fjdNJHXJtsxeTPZNG4QX91hUkuGVIlbgyJa7m/pb0iTIU9TYEvsdiUKERw/vPv50rXebyDFRy4woQYgfxurafw2zQg6GG9pTbkra7+5Ibuypzu6kggnBNGqHA/Wp52TkOMvkRovtROrt9Nf+F4dsLX9KrqNY06x1HGf97BC8aCp8MMGt995J7kOWcBKH5PbsGyGp1scEuWeWRpFRxaQSB0fAQvWR1DUJawXTcIENWNHOFFtoJiliG9xawcGgRWWHvsiB7QrjfrPRqPrkmw6GDId5wMj1Ln/A6EenuhDrZjRGL1olm3IrC42YV0/o1a0uwuTHmjyOwk7mkIfZeXsGwmF9ydGtdCB/9wDIGgjJOEGL2ZGfiUb8TwlvtiJ4QSaB/k6cTL/JL50NITlYu5BRqJWEqm1NHd5aH67BCPRCklYh/jK+Y8gTE3W4GRXRAt8pAa1E7dgLaQaA5FcB+GtkI7S8ZZ80dr2W2rZfk09oGCY3y8c0cUs+SHnbhtbEeJIuQ9yUqS5I/pWx4CULmImOTvWwBWJ9KgKeCCNgxCLx/xKikC4w/slO3uZyuKEsmsQNWPnAsEvhgQ8mK4IvXVAXYj0qPYGVyRsm6FGb01BuxvHlS5AYrS4p4aXLSelFJ1IOxjJEuKbdaHvnAvXBd5/GHSy1h5I4gBYEZbmlKnYncu3yTXM5PSey0+1a9uHvaB5Asn2Wl9Kuj2BItvGGVl+rewYWisDbi0nMNRGLnfh3Yum+K54jtGkc+ooJ4yOq7OnYbjpZDERMGvcXl6oVBx+eZBMolh1YwuNGrRfvhnaHDg/f4Z8TkedD+kbZ40/Ws/yzfTOLS1F5+odYDYxxxsVIZ4q3w5Xjq5ce7zin3WCRdA7zuuJX9n1Lv+wRYRGi8cSE2YCFUVOzguX/XE7Xmxbsk"
}
]
}

200 Response example

{
"id": "wa-1f04s-lqc9q-xxxxxxxxxxxxxxxx",
"name": "My Imported Wallet",
"network": "EthereumSepolia",
"status": "Active",
"dateCreated": "2023-04-14T20:41:28.715Z",
"imported": true,
"signingKey": {
"curve": "secp256k1",
"scheme": "ECDSA",
"publicKey": "e2375c8c9e87bfcd0be8f29d76c818cabacd51584f72cb2222d49a13b036d84d3d"
}
}

Export Wallet

POST /wallets/{walletId}/export

  • This endpoint is not enabled by default. Contact Dfns to have it activated.

  • User action signature required. See User Action Signing for more information.

  • Request headers required. See Request Headers for more information.

  • Authentication required. See Authentication Headers for more information.

Dfns secures private keys by generating them as MPC key shares in our decentralized key management network. Our goal is to eliminate all single points of failure (SPOFs) associated with blockchain private keys.

In certain circumstances, however, customers require Dfns to export a wallet (export its private key) . In this case, Dfns exposes the following endpoint which can be used in conjunction with our export SDK.

Dfns can not guarantee the security of exported keys as we have no way to control blockchain transactions once the single point of failure has been reconstituted. For this reason, this feature is restricted to customers who have signed a contractual addendum limiting our liability for exported keys. Additionally, exported keys can no longer be used to sign within the Dfns platform. Please contact your sales representative for more information.

Required Permissions

Name

Conditions

Wallets:Export

Always Required

Wallet Export Flow

The wallet private key which you need to export, will never be transmitted through Dfns system in one piece, or in clear (un-encrypted). The process follows this flow:

  1. On your side (client-side), with the help of our export SDK library, you create an "export context" locally. This will generate an encryption/decryption key pair to perform the export in a secure way. This step corresponds to this line in our SDK wallet export example.

  2. You then call the Wallet Export endpoint, providing the API with the previous encryption key for secure export. This step corresponds to this line in our SDK wallet export example.

  3. On Dfns side, the export encryption key gets transmitted to each node of your Signing Cluster (Your Signing Cluster is the network of nodes, also referred as "signers", where your wallet private key shares are securely stored). Each signer node will encrypt the corresponding key share to be exported. All encrypted key shares are then transmitted back to you.

  4. On your side (client-side), with the help of our export SDK library, you will then decrypt each encrypted key share, and re-compose the key shares into a single private key (the wallet private key). This step corresponds to this line in our SDK wallet export example.

Request body

Property

Type - Required/Optional

Description

encryptionKey

String - Required

The public key of an asymmetric key pair used to encrypt the key shares prior to transmission.

supportedSchemes

Object Array - Required

An object with the format shown below.

supportedSchemes

Property

Type - Required/Optional

Description

protocol

String - Required

Always "CGGMP21" for now. Additional signature schemes will be added in the future.

curve

String - Required

Always "secp256k1" per above.

Example JSON

{
"encryptionKey": "AQNiFCgqtXFvRdNVciLzZ0hjZxumwtP0hfCrUDsymzWU5A==",
"supportedSchemes": [
{
"protocol": "CGGMP21",
"curve": "secp256k1"
}
]
}

200 Response example

{
"publicKey": "0363fd944987c22382c2f34f8ffc53e1fc1e2def96baacd9cbaa5ff51bfb308e2b",
"minSigners": 3,
"curve": "secp256k1",
"protocol": "CGGMP21",
"encryptedKeyShares": [
{
"signerId": "9R4OQb12f8PrEQwFmwZ58ZsNHs6EcGQPWF3fSzhXbVk=",
"encryptedKeyShare": "Op1j4tQYry0GA5rCgqNXoP+feWxdCNLwkx0rS6GKPD/JtfuXAIwEhurlo60ckAo2L/w5KLoq8RH41GR2TlNJgcvtqa2a+hCgeM/X86hjeqhqWaKq50PkNS1RxrIgrzuL3UkxyvStYyiZMcdWalSYCSrE5rJ61dSD+EpflX34VjAC2GnNa+T3TNam9455tCp56HqNaqDsEXTg+rvEkYs8VxSBm9enRbRepZvQ0YU+vvJotn5rkef7R8aR++Y1sfcKWMG8b4ivdDth1jdFXDmogq94nwloRlohmRaaoSRU6A7HwbDcgwreV/MDcOMK7n8QgSGDw17o/JID4OUtkL7V5P5Jm9ENVp5d1I/UdoRONTk9zlGMcb4Qje8="
},
{
"signerId": "lGcHWQmdLtJ+4S+RIBFq704/Nox2bugUctVeLL0wPW8=",
"encryptedKeyShare": "617Qp7YyF+tlbNzsGF1dmnLlm2F6CFBVpwSg/o2RWAyUmCQAULPn0yXXFmYqCJuJ93wPhXeA2GMXjbZDTMRtSpI1BRxBAtDaQSgQeO2z59/VxXoFvCQMCl+QsrwzoisAnS3qG7HnpltT53Bf5B8h5k/Ezb0zMWFrz2y6X9Oodh/yIQDtCUIUgImkKtfTApOLOZgR+o0xcljLR5w2uqDNS1ED16ZXLocLqt3gqhxfApHNT5WsT6q3P02svUn9uztts8LZliAyBZxted1rqVPaoTjrmGoOCjJdTk4PP7EuYGa7o9C69jmdJycPXjyuWQFp8fo+nNwm5qEC+oPG7aeoC8A2r1x1b/O8HjGxSl+pjY+Z/shaIg+5Xzw="
},
{
"signerId": "EX5PdJFcutVTJCgAcSGGGy264JwnrOLLyrZIqMHG67I=",
"encryptedKeyShare": "YvUd5t8yNxilhZujk3QUaTDy/ZL4smL3s9Av82dQTpoV6BnWq3EZfPVjiYSB64o5Louq7PCmqzuP/30A35RSPFEYexIRlS6koIcod3J/mmVeV/Huw1D+J9xBfanCN1FgsnO4zlLRSpNmysuBRgkHV7KHf0rbMVQkDa6daZa8CMahMW15ASLx8Tmfg7xA22VgFI9emXMwi55RDsn4xFL238lrGKjfKUcf6awxNX62/9o6A2FehoFIOVDX/4nRXysa4mqRNhNF2PIOZYr5UtraTeyO+xvASMgvr4UH49YFFbKkf3YrEp9u/FPmeahD4kRal56tXYjRQ2kCAl2H2Qy5SOi0G3knL7e3rAcIHArimmd4bqujVLT2igI="
},
{
"signerId": "ZokM6nUhGXHYhtQYE/NTeBEz5udvx13Ympcd1raQ4Fc=",
"encryptedKeyShare": "W8pFNu7hpLBHCk4xnR7sIxZKfEEiRNTG5oWyemDGoaZ+qqJ7rzLVbpK0MdkNNVU9NSRMr3pIpDKvo2VkwZq+PDhfNaHHOOHexlzPIcu5pfRS/RlJWZAue5Ems1zNkM13qKLjkarvwNVCfoUUTtUGnzfFw34W/JvkMA3yOTFs0B8EyCfrtiEixrzPgvmM9/D3Nej3nzZRkLCImralwMxOUFj/xo9DG4y7KiAICiMk1v36tgXHj7jo5sC+Z2JVzNHRsg/zNshUeuTlb7vy5cgkXXuz4EO6nivJOvCNuOPPMIQlx8AA/ATxWt1ZS2+IgWwr/BjEqXW9xEMCLpXQwOoO+7SKR4C7d3goG5OZweGYKHwQDc6f47HQmo4="
},
{
"signerId": "KaGnB8iWVpRKBRh+/sAJ0gz1cAZtjhHPufGRgkOXENo=",
"encryptedKeyShare": "7ZZMXgm31nIA3Dhaq45GzAbis67Eq7IQoy3orM/xm0x8xOmM/EXj1vWiC0PXx/vnFvdHg/jQSfBEBeQV0lV/lvVUEJD3D4rD+7GffEkNLIz71gKlJ4pZYyPnDcXSzsrcapREWa4j6ZGVNEYrjcXroVbLqa8xhStww5E0XTdQ0RMLKcmzEyDeF5BQuZKik2Q8JRqJmGhwtwxdCkG2SR4m28BbIHGJzKkQDCW92dq6Wls2rpf1Y0aaVzOYEJkbib8g0ulZS4EdR7FF/mp4cAAuZPWhoxA9RB6Z3WQUvuH7fIOZ1t43XF+nQ1WYgXKqnv48r4gsuLjy+9oD7xDydjqrbIF0c6gqYRdcR8z/CjYaGrHxAEdbauioNwo="
}
]
}

Did this answer your question?