Sign EVM Transaction
Once you have built an Ethereum transaction object, you can ask the user to sign it by using thesignTransaction
function in the MetaKeep SDK. The function expects a non-empty reason
which is shown to the user at the time of transaction signing.
This function is compliant with the official Ethereum sign transaction API https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_signtransaction
await sdk.signTransaction(
// Eth transaction object
{
type: 2,
from: userEthAddress,
to: "0x97706Df14A769E28EC897dAc5Ba7bCfa5AA9C444",
value: "0x2710",
nonce: "0x1",
data: "0x0123456789",
gas: 23,
maxFeePerGas: 1000,
maxPriorityFeePerGas: 999,
chainId: 137,
},
// signing reason
"reason",
);
Here's a reference implementation of this code: https://jsfiddle.net/passbird/d1s30g8b/
Sign Solana Transaction
Once you have built a Solana transaction object using @solana/web3.js
, you can ask the user to sign it by using thesignTransaction
function in the MetaKeep SDK. The function expects a non-empty reason
which is shown to the user at the time of transaction signing.
If you are not using @solana/web3.js
, you need to serialize the transaction message that needs to be signed before sending it to the MetaKeep SDK.
Solana versioned transactions are supported
// Build the solana transfer transaction
const tx = new Transaction().add(
SystemProgram.transfer({
fromPubkey: fromPublicKey,
toPubkey: toPublicKey,
lamports: 1 * LAMPORTS_PER_SOL
})
);
await sdk.signTransaction(
// Transaction object
tx,
// Signing reason
"transfer 1 SOL"
);
// Build the solana transfer versioned message
const messageV0WithLookupTable = new TransactionMessage({
payerKey: payerPublicKey,
recentBlockhash: (await connection.getRecentBlockhash()).blockhash,
instructions: [
SystemProgram.transfer({
fromPubkey: fromPublicKey,
toPubkey: toPublicKey,
lamports: amountToTransfer * LAMPORTS_PER_SOL
})
]
}).compileToV0Message([lookupTableAccount]);
// Build the versioned transaction
const tx = new VersionedTransaction(messageV0WithLookupTable);
await sdk.signTransaction(
// Transaction object
tx,
// Signing reason
"transfer 1 SOL"
);
// Serialized transaction message in hex format.
// This is the data that needs to be signed
const serializedTransactionMessage = "0xabcd.........."
await sdk.signTransaction(
// Serialized Solana transaction message
{
serializedTransactionMessage: serializedTransactionMessage
},
// signing reason
"transfer 1 SOL"
);
Here's a reference implementation of this code:
- Legacy transaction: https://codesandbox.io/s/metakeep-sign-solana-transaction-qu5rqu?file=/src/App.js
- Versioned transaction: https://codesandbox.io/s/metakeep-sign-solana-versioned-transaction-hpclk4?file=/src/App.js
The latest
@solana/web3.js
supported version is 1.75.0Let us know if you would like us to support a more recent version :)
Sign EOS Transaction
Once you have built a raw EOS transaction, you can ask the user to sign it by using thesignTransaction
function in the MetaKeep SDK. If the signature generation also requires a chainId, you can send it in the extraSigningData
field. Note that the action data needs to be sent as a serialized hex string.
The function also expects a non-empty reason
which is shown to the user at the time of transaction signing.
await sdk.signTransaction(
// Transaction object
{
// Raw EOS transaction
"rawTransaction": {
"expiration": "2023-05-06T01:23:45",
"ref_block_num": 12345,
"ref_block_prefix": 67890,
"max_net_usage_words": 0,
"max_cpu_usage_ms": 0,
"delay_sec": 0,
"context_free_actions": [],
"actions": [{
"account": "eosio.token",
"name": "transfer",
"authorization": [{
"actor": "myaccount",
"permission": "active"
}],
// Send action data as a serialized hex string.
"data": "0000000000ea305500000000487a2b000000000000000004454f530000000000"
}],
"transaction_extensions": []
},
"extraSigningData": {
// If chainId is part of the signature generation,
// send it inside extraSigningData field.
"chainId": "b20901380af44ef59c5918439a1f9a41d83669020319a80574b804a5f95cbd7e"
}
},
// signing reason
"reason",
);
Here's a reference implementation of this code: https://jsfiddle.net/passbird/xpLwjn53/
Response
signTransaction
returns a promise which succeeds when the sign operation is successful. The response looks like this-
{
status: "SUCCESS",
//The RLP encoded transaction, ready to be sent using web3.eth.sendSignedTransaction.
signedRawTransaction: "0x02f86c8189018203e78203e8179497706df14a769e28ec897dac5ba7bcfa5aa9c444822710850123456789c080a01a84678f385553358386051464a252fa25d019335deb20262eb231d4ec146730a00e6f1944e872430b7e04af6dd68ece90e2a9995a7abd827b50588602523b5256",
// The transaction hash for the RLP encoded transaction.
transactionHash: "0xe02497f6d7d4b52197a35db6115633b34802f90eaa98e894791999ca0d6b11f8",
// Signature of the signed transaction. The signature encodes the r, s and v parameters
// from appendix F of the yellow paper in big-endian format.
// Bytes 0…32 contain the r parameter, bytes 32…64 the s parameter and the last byte the v parameter.
signature: "0x1a84678f385553358386051464a252fa25d019335deb20262eb231d4ec1467300e6f1944e872430b7e04af6dd68ece90e2a9995a7abd827b50588602523b525600",
r: "0x1a84678f385553358386051464a252fa25d019335deb20262eb231d4ec146730",
s: "0x0e6f1944e872430b7e04af6dd68ece90e2a9995a7abd827b50588602523b5256",
v: "0x0"
}
{
"status": "SUCCESS",
// Signature in hex format
"signature": "0x023d9a5700b77971b8de539936143e0d82808809b856cc9ab9bcc41a02a3794ec516a44db6ed666f3e4f7549ae91939062ce076a9ef419febc21c41eebb98f0a"
}
{
"status": "SUCCESS",
"signature": "SIG_K1_K1YY3maW1vHjQmmtciiQkkzPaUcpPdCQ631oMqayz4Z3TG9xhjNQwzqL3VCQPV1ZfYTQ14hkoRBkFaUwwrAngLedAxhog6"
}
Error status
signTransaction
returns a promise which throws an error when the sign operation is unsuccessful. The error object looks like so-
{
status: "USER_CONSENT_DENIED"
}
Here's a table of all possible error status returned by the SDK
Status | Description |
---|---|
USER_REQUEST_DENIED | User has denied the sign operation. In this case, you should ask the user if they want to try again. |
INVALID_REQUEST | Invalid data passed to sign operation. Please get in touch with us if you are unable to fix this. |
MISSING_NONCE | The nonce is missing. Please specify nonce for the transaction. |
MISSING_GAS | Gas is missing. Please specify gas for the transaction. |
INVALID_GAS_FEE_PARAMS | The transaction contains gasPrice maxFeePerGas and maxPriorityFeePerGas . Please specify either gasPrice or maxFeePerGas and maxPriorityFeePerGas |
MISSING_GAS_PRICE | Gas price is missing for type 1 transactions. Please specify gasPrice . |
MISSING_MAX_FEE_PER_GAS | The max fee per gas is missing for type 2 transactions. Please specify both maxFeePerGas and maxPriorityFeePerGas |
MISSING_MAX_PRIORITY_FEE_PER_GAS | The max priority fee per gas is missing for type 2 transactions. Please specify both maxFeePerGas and maxPriorityFeePerGas |
APP_ID_REQUIRED | No app id provided when initializing the SDK. You can find the app id in MetaKeep Developer Console. |
APP_NOT_FOUND | Provided app id is invalid. You can find the correct app id in MetaKeep Developer Console. |
SOMETHING_WENT_WRONG | Unknown error happened. Please get in touch with us if you continue seeing this error. |
© Copyright 2024, Passbird Research Inc.