搭建 Web3 钱包#
请确保已完成了准备工作,可直接通过此案例,熟悉钱包管理、各公链数据的查询、交易构建和广播。
第一步:生成钱包助记词及地址#
你可以使用我们提供的 签名 SDK 创建钱包助记词及地址。
npm install#
首先需要安装到最新的签名 SDK 版本,以 EVM 网络为例:
npm install @okxweb3/crypto-lib
npm install @okxweb3/coin-base
npm install @okxweb3/coin-ethereum
本地构建#
- 下载项目源码
git clone https://github.com/okx/js-wallet-sdk.git
- 运行构建脚本
sh build.sh
以 EVM 网络为例,可以依照下述代码,使用签名 SDK 创建一个 EVM 钱包对象,并且推导出所对应地址。
import { bip39, BigNumber } from "@okxweb3/crypto-lib";
import { EthWallet,MessageTypes } from "@okxweb3/coin-ethereum";
// eth wallet
let wallet = new EthWallet();
// get mnemonic
let mnemonic = await bip39.generateMnemonic();
console.log("generate mnemonic:", mnemonic);
// get derived key
const hdPath = await wallet.getDerivedPath({ index: 0 });
let derivePrivateKey = await wallet.getDerivedPrivateKey({ mnemonic: mnemonic, hdPath: hdPath });
console.log("generate derived private key:", derivePrivateKey, ",derived path: ", hdPath);
// get new address
let newAddress = await wallet.getNewAddress({ privateKey: derivePrivateKey });
console.log("generate new address:", newAddress.address);
// get the public key
let publicKey = newAddress.publicKey;
console.log("the corresponding public key:", publicKey);
演示程序#
我们准备了一个开源演示程序,用于展示我们上述涉及到签名 SDK 的功能。 获取演示程序源码点击这里。
第二步:创建账户#
你在上一步,已经生成了助记词和地址。现在你可以创建账户 (AccountId) 来聚合多个地址,进行批量查询代币余额和交易历史。
说明
通常情况,Web3 钱包有三个概念:
- 钱包,谁拥有助记词,谁就拥有钱包。
- 账户,基于 BIP-44 规范,一套助记词下可以派生多个账户。
- 地址,每个账户下的每个链,对应一个地址。
- 钱包,谁拥有助记词,谁就拥有钱包。
- 账户,基于 BIP-44 规范,一套助记词下可以派生多个账户。
- 地址,每个账户下的每个链,对应一个地址。
调用接口来创建钱包账户。
例如,同时订阅不同链上的同一地址,实现如下:
//定义你的参数
const addresses = [
{
"chainIndex":"1",
"address":"0x561815e02bac6128bbbbc551005ddfd92a5c24db",
},
{
"chainIndex":"10",
"address":"0x561815e02bac6128bbbbc551005ddfd92a5c24db",
}
];
const getCreateAccountBody = {
addresses: addresses,
};
//定义辅助函数
const getCreateAccountData = async () => {
const apiRequestUrl = getRequestUrl(
apiBaseUrl,
'/api/v5/wallet/account/create-wallet-account'
);
return fetch(apiRequestUrl, {
method: 'post',
headers: headersParams,
body: JSON.stringify(getCreateAccountBody),
})
.then((res) => res.json())
.then((res) => {
return res;
});
};
const { data: createAccountData } = await getCreateAccountData();
第三步:构建并发送交易#
获取签名所需信息#
首先,调用 POST /api/v5/wallet/pre-transaction/sign-info
接口,查询签名所需要的一些数据,例如 EVM 链的 gas price、gas limit、nonce 等。
//定义你的参数
// EVM
const postSignInfoBody = {
chainIndex: '1',
fromAddr: '0xdf54b6c6195ea4d948d03bfd818d365cf175cfc2',
toAddr: '0x1e80c39051f078ee34763282cbb36ffd88b40c65',
txAmount: '123000000000000',
extJson: {
inputData: '041bbc6fa102394773c6d8f6d634320773af4'
}
};
// TRON
const postSignInfoBody = {
"chainIndex": "195",
"fromAddr": "TDnSmJ15nmwg5jmYmXWFVgBX53XxfbNHsC",
"toAddr": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"txAmount": "0",
"extJson": {
"permissionType": 1,
"feeLimit": 300000,
"inputData": "0x095ea7b3000000000000000000000000d73c5e36d47eed32f0327f9d3f04b49384e90fab0000000000000000000000000000000000000000000000000000000000000000"
}
};
const postSignInfoBody = {
chainIndex: '1',
fromAddr: '0xdf54b6c6195ea4d948d03bfd818d365cf175cfc2',
toAddr: '0x1e80c39051f078ee34763282cbb36ffd88b40c65',
txAmount: '123000000000000',
extJson: {
inputData: '041bbc6fa102394773c6d8f6d634320773af4'
}
};
//定义辅助函数
const signInfoData = async () => {
const apiRequestUrl = getRequestUrl(
apiBaseUrl,
'/api/v5/wallet/pre-transaction/sign-info'
);
return fetch(apiRequestUrl, {
method: 'post',
headers: headersParams,
body: JSON.stringify(postSignInfoBody),
})
.then((res) => res.json())
.then((res) => {
return res;
});
};
const { data: signInfoData } = await signInfoData();
验证地址构建交易#
使用签名 SDK 先验证地址合法性再构建交易
// Verify address
let valid = await wallet.validAddress({
address: newAddress.address
});
console.log("verify address isValid:", valid.isValid);
// Sign a transaction
let signParams = {
privateKey: derivePrivateKey,
data: {
to: newAddress.address,
value: new BigNumber(0),
nonce: 5,
gasPrice: new BigNumber(100 * 1000000000),
gasLimit: new BigNumber(21000),
chainId: 42
}
};
let signedTx = await wallet.signTransaction(signParams);
console.log("signed tx:", signedTx);
广播交易#
调用接口,交易广播到链上。
//定义你的参数
const postSendTransactionBody = {
"signedTx": "0x02f8720182029f8411e1a3008504bbe2e94682520894d73c5e36d47eed32f0327f9d3f04b49384e90fab85e8d4a5100080c080a0ba380a9be31efabc4c8cfccbb555f8af3c21073d6eca01f180ebebb8942c6f30a0779e6e16a504c413cb9902ceb33ab7e89a533bc13b74477dfa6b6c76dc41fac2
"accountId": "5f45a951-4a8b-4cd9-b20a-3b337b71efcc",
"chainIndex": "1",
"address": "0x238193be9e80e68eace3588b45d8cf4a7eae0fa3",
};
//定义辅助函数
const sendTransactionData = async () => {
const apiRequestUrl = getRequestUrl(
apiBaseUrl,
'api/v5/wallet/pre-transaction/broadcast-transaction'
);
return fetch(apiRequestUrl, {
method: 'post',
headers: headersParams,
body: JSON.stringify(postSendTransactionBody),
})
.then((res) => res.json())
.then((res) => {
return res;
});
};
const { data: sendTransactionData } = await sendTransactionData();
广播后,你将收到如下的响应:
{
"code": 0,
"msg": "success",
"data": [{
"orderId": "469356614923743232"
}]
}
说明
点击查看 orderId 的定义
第四步:查询交易详情#
当发送交易后,使用接口来获取交易详情信息。也可查看查询特定 Tx来获取交易详情信息。
//定义你的参数
const params = {
accountId: '13886e05-1265-4b79-8ac3-b7ab46211001',
orderId: '469356614923743232',
chainIndex: '1'
};
//定义辅助函数
const getTransactionDetailData = async () => {
const apiRequestUrl = getRequestUrl(
apiBaseUrl,
'/api/v5/wallet/post-transaction/transaction-detail-by-ordid',
params
);
return fetch(apiRequestUrl, {
method: 'get',
headers: headersParams,
})
.then((res) => res.json())
.then((res) => {
return res;
});
};
const { data: transactionDetailData } = await getTransactionDetailData();
查询详情成功后,你将收到如下的响应:
{
"code": 0,
"msg": "success",
"data": [
{
"chainIndex": "1",
"orderId": "469356614923743232",
"txhash": "0xcbf411766d65f3cf92839ababa73c4afec69a83442e8b67a68b5104b50a04ejb",
"blockHash" : "0x3ee63382b883fc40e35da6023fb341dd01cd2ec011f992bb54cf312f517740c9",
"blockHeight" : "19235519",
"blockTime" : "1708026551000",
"feeUsdValue" : "138.846919",
"fees" : "49102595635945621",
"gasLimit" : "2000000",
"gasPrice" : "87504603347",
"gasUsed" : "561143",
"txType": "0",
"txTime": "0",
"txStatus": "0",
"txDetail": [
{
"iType" : "0",
"txAmount": "0",
"tokenAddress":""
"contractCall" : true,
"fromAddr" : "0x3ee63382b883fc40e35da6023fb341dd01cd2ec011f992bb54cf312f517740c9",
"toAddr" : "0x3ee63382b883fc40e35da6023fb341dd01cd2ec011f992bb54cf312f517740c9",
"logIndex" : "-1",
"status" : "SUCCESS"
}
]
}
]
}
此外,你还可以通过订阅 Webhook,实时准确地了解交易发送后的状态,查看详情。
到这里,你基本上已经实现了开发一款 Web3 钱包所需的部分基础功能。
此外,钱包 API 提供了丰富接口,全方位满足 Web3 钱包开发者的需求,请查看下方章节查看更多内容。