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* |
|
| 1 | ASA | 0 |
|
| 1 | ERC-20, ERC-721 | 50 |
|
| 1 | ERC-20, ERC-721 | 0 |
|
| 1 | ERC-20, ERC-721 | 50 |
|
| 1 | N/A | 2 |
|
| 1 | ERC-20, ERC-721 | 50 |
|
| 2 | N/A | N/A |
|
| 1 | ERC-20, ERC-721 | 12 |
|
| 1 | ERC-20, ERC-721 | 0 |
| No testnet support | 1 | ICRC(not generic) | 1 |
| No testnet support | 1 | N/A | 20 |
|
| 2 | N/A | N/A |
| No testnet support | 1 | N/A | 12 |
| No testnet support | 1 | N/A | 1 |
|
| 1 | ERC-20, ERC-721 | 50 |
|
| 2 | N/A | N/A |
|
| 1 | ERC-20, ERC-721 | 50 |
|
| 1 | N/A | 0 |
|
| 1 | SPL/SPL2022 | 0 |
|
| 1 | SEP-41/Classic | 0 |
|
| 2 | N/A | N/A |
|
| 1 | TEP-74/Jetton | 0 |
|
| 1 | TRC10/20/721 | 19 |
|
| 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
orEdDSA
.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.
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.
Required Permissions
Name | Conditions |
| Always Required |
| only required if |
Request
Property | Type - Optional | Description |
| String | Network used for the wallet (See Supported Networks + Pseudo Network for possible values) |
| String - Optional | Name given to the wallet |
| String List - Optional | List of tags to be created for this wallet. If specified, requires the |
| 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 |
| 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 walletnetwork
- string - Network used for the wallet (See Supported Networks for possible values)name
- (Optional) string - Name given to the walletaddress
- (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 ofActive
,Archived
.signingKey
- object - Info about the signing key corresponding to that walletscheme
- string - Supported schemes areECDSA
orEdDSA
curve
- string - Key curve. Can beed25519
orsecp256k1
publicKey
- string - Hex-encoded value of public key
dateCreated
- string - ISO 8601 date string when wallet was createdimported
- (Optional) boolean - istrue
if the wallet is an imported wallet.exported
- (Optional) boolean - istrue
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 walletcustodial
- 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.
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.
Required Permissions
Name | Conditions |
| Always Required |
Path parameters
Path parameter | Description |
| Unique identifier of the |
Request
Property | Type - Optional | Description |
| String - Optional | Name given to the wallet |
| 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.
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.
Required Permissions
Name | Conditions |
| Always Required |
Request
Request body fields | Required/Optional | Description | Type |
| 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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
Response
The response body is the Wallet. The Wallet object has those fields:
id
- string - ID of the walletnetwork
- string - Network used for the wallet (See Supported Networks for possible values)name
- (Optional) string - Name given to the walletaddress
- (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 ofActive
,Archived
.signingKey
- object - Info about the signing key corresponding to that walletscheme
- string - Supported schemes areECDSA
orEdDSA
curve
- string - Key curve. Can beed25519
orsecp256k1
publicKey
- string - Hex-encoded value of public key
dateCreated
- string - ISO 8601 date string when wallet was createdimported
- (Optional) boolean - istrue
if the wallet is an imported wallet.exported
- (Optional) boolean - istrue
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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Query parameters
Query string parameter | Required/Optional | Description | Type |
| 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 |
| 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 |
| Optional | Maximum number of items to return. Default to 50. | Number |
| Optional | Opaque token used to retrieve the next page. Returned as | 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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
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)
Get SPL tokens.
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)
Get SPL 2022 tokens.
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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
Query parameters
Query string parameter | Required/Optional | Description | Type |
| Optional | Maximum number of items to return. Default to 50. | Number |
| Optional | Opaque token used to retrieve the next page. Returned as | 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.
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.
Required Permissions
Name | Conditions |
| Always Required |
Path parameters
Path parameter | Description |
| Unique identifier of the |
Request body
Property | Type | Description |
| 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.
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.
Required Permissions
Name | Conditions |
| Always Required |
Path parameters
Path parameter | Description |
| Unique identifier of the |
Request body
Property | Type | Description |
| 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.
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.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
Native Token
Transfer the native token of the network. All networks support the native token type.
Request body
Property | Type | Description |
| String |
|
| String | The destination address |
| String | The amount of native tokens to transfer in minimum denomination |
| (Optional) String | The priority that determines the fees paid for the transfer [1] |
| (Optional) String | The memo or destination tag [2] |
| (Optional) String | A unique ID from your system. It can be leveraged to be used as an idempotency key (read more here) |
All EVM compatible networks and Bitcoin support
priority
. Not supported for other networks. The accepted values areSlow
,Standard
andFast
. 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.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 |
| Required |
| String |
| Required | The asset ID of the token | String |
| Required | The destination address | String |
| 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 |
| Required |
| String |
| Required | The ERC20 contract address | String |
| Required | The destination address | String |
| Required | The amount of tokens to transfer in minimum denomination | String |
| 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 |
| Required |
| String |
| Required | The ERC721 contract address | String |
| Required | The destination address | String |
| Required | The token to transfer | String |
| 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 |
| Required |
| String |
| Required | The mint account address | String |
| Required | The destination address | String |
| Required | The amount of tokens to transfer in minimum denomination | String |
| 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 |
| Required |
| String |
| Required | The mint account address | String |
| Required | The destination address | String |
| Required | The amount of tokens to transfer in minimum denomination | String |
| 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 |
| Required |
| String |
| Required | The asset issuer address | String |
| Required | The asset code | String |
| Required | The destination address | String |
| Required | The amount of tokens to transfer in minimum denomination | String |
| 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 |
| Required |
| String |
| Required | The jetton master address | String |
| Required | The destination address | String |
| 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 |
| Required |
| String |
| Required | The token ID | String |
| Required | The destination address | String |
| 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 |
| Required |
| String |
| Required | The smart contract address | String |
| Required | The destination address | String |
| 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 |
| Required |
| String |
| Required | The smart contract address | String |
| Required | The destination address | String |
| Required | The token to transfer | String |
Sample request body
{
"kind": "Trc721",
"contract": "TKgnDMWHYmwH24REe9XnrnwcNCvtb53n8Q",
"to": "TQJNezrbfJ3akrGgR7eM2fWyFpsKeM8wzN",
"tokenId": "1"
}
Response Statuses
Status | Definition |
| The request is pending approval due to a policy applied to the wallet |
| 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) |
| The transaction has been successfully written to the mempool |
| The transaction has been confirmed on-chain by our indexing pipeline |
| Indicates a system failure to complete the request |
| 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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
| Unique identifier of the transfer request. ex. |
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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
Query parameters
Query string parameter | Required/Optional | Description | Type |
| Optional | Maximum number of items to return. Default to 50. | Number |
| Optional | Opaque token used to retrieve the next page. Returned as | 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.
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.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
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 |
| The request is pending approval due to a policy applied to the wallet |
| 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) |
| The transaction has been successfully written to the mempool |
| The transaction has been confirmed on-chain by our indexing pipeline |
| Indicates a system failure to complete the request |
| The request has been rejected by a policy approval action |
Algorand: Broadcast Transaction
Request body
Property | Type | Description |
| String | For Algorand, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Bitcoin, always |
| Hex String | The hex encoded PSBT as shown below |
| (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 |
| String | For Cardano, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| Required - String |
|
| Required - String | Blockchain address of target contract or payee. |
| (Optional. Required only if making a payment) - String (representing a integer eg | Amount of the native currency to transfer denominated in WEI. |
| (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. |
| (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 |
| (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 |
| String |
|
| String | Blockchain address of target contract or payee. |
| (Optional - Required if making a payment) - String (representing an integer eg | Amount of the native currency to transfer denominated in WEI. |
| (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. |
| (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 |
| (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. |
| (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. |
| (Optional) String (representing an Integer) | The maximum amount for gas willing to be paid for the transaction. If omitted, it will be calculated automatically. |
| (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 |
| String |
|
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Polkadot, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Solana, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Stellar, always |
| Hex | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Tezos, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Tezos, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Tron, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For XRP Ledger, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
| Unique identifier of the transaction request. ex. |
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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
Query parameters
Query string parameter | Required/Optional | Description | Type |
| Optional | Maximum number of items to return. Default to 50. | Number |
| Optional | Opaque token used to retrieve the next page. Returned as | 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.
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.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
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 |
| The request is pending approval due to a policy applied to the wallet |
| 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) |
| The signature is complete and available in the response body |
| The signature has been confirmed on-chain by our indexing pipeline |
| Indicates an internal system failure to complete the request |
| The request has been rejected by a policy approval action |
Algorand: Generate Signature
Request body
Property | Type | Description |
| String | For Algorand, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String |
|
| Hex String | The hex encoded PSBT as shown below |
| (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 |
| String |
|
| String | The generic message hex encoded. |
| (Optional) String | Either |
| (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 |
| String | For Cardano, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String |
|
| Hex String | The hex encoded |
| (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 |
| String |
|
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String |
|
| String | The original message hex encoded. |
| (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 |
| String |
|
| Map<String, TypedDataField[]> | Type definitions. |
| Eip712Domain | Domain separator. |
| Object | Structured message to sign. |
| (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 |
| String | Field name. |
| String | Field type. |
Eip712Domain
field | Type | Description |
| String | Name of the signing domain. |
| String | Current major version of the signing domain. |
| Integer | Chain ID. |
| String | The address of the contract that will verify the signature. |
| 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 |
| String |
|
| String | The hash digest in hex. |
| (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 |
| String | For Polkadot, always |
| Hex String | The unsigned hex encoded signer payload as shown below |
| (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 |
| String | For Solana, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Stellar, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Tezos, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String | For Tron, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String |
|
| Hex String | The serialized signing message BoC |
| (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 |
| String |
|
| String | The hash digest in hex. |
| (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 |
| String | For XRP Ledger, always |
| Hex String | The unsigned hex encoded transaction as shown below |
| (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 |
| String |
|
| Hex String | The hash digest in hex. |
| (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 |
| Required |
|
| Required | The original message hex encoded. |
| (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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
| Unique identifier of the signature request. ex. |
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.
Request headers required. See Request Headers for more information.
Authentication required. See Authentication Headers for more information.
Required Permissions
Name | Conditions |
| Always Required |
Parameters
Path parameters
Path parameter | Description |
| Unique identifier of the |
Query parameters
Query string parameter | Required/Optional | Description | Type |
| Optional | Maximum number of items to return. Default to 50. | Number |
| Optional | Opaque token used to retrieve the next page. Returned as | 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 |
| Always Required |
| 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:
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.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.
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.
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 |
curve | String - Required | Always |
minSigners | Integer - Required | Always |
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 |
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 |
| 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:
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.
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.
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.
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="
}
]
}