不同语言的 Forge SDK 对原子互换的交易都提供了很好的封装,基于 SDK 实现原子互换也比较简单,注意这里实现的是纯代码层面的原子互换,因为交换的双方都是在代码里面生成的,现实世界中的原子交换可能发生在两个用户或者用户和应用之间,比如典型的 B2C 购买和 C2C 的购买。
用 JavaScript SDK 做原子交换
const ForgeSDK = require('@arcblock/forge-sdk');
const { getRandomBytes, Hasher } = require('@arcblock/mcrypto');
const sleep = timeout => new Promise(resolve => setTimeout(resolve, timeout));
// Connect to 2 chains that are used to do atomic-swap
ForgeSDK.connect('http://localhost:8210/api', { name: 'offer-chain' });
ForgeSDK.connect('http://localhost:8211/api', { name: 'demand-chain' });
(async () => {
try {
const buyer = ForgeSDK.Wallet.fromRandom();
const seller = ForgeSDK.Wallet.fromRandom();
console.log({ buyer: buyer.toAddress(), seller: seller.toAddress() });
const declare = async (wallet, moniker) => {
let hash = await ForgeSDK.declare({ moniker, wallet }, { conn: 'offer-chain' });
console.log(`declare.appChain.${moniker}`, hash);
hash = await ForgeSDK.declare({ moniker, wallet }, { conn: 'demand-chain' });
console.log(`declare.assetChain.${moniker}`, hash);
};
// declare
await declare(buyer, 'buyer');
await declare(seller, 'seller');
// 3. ensure asset for seller on app chain
const ensureSellerAsset = async () => {
const [hash, address] = await ForgeSDK.createAsset(
{
moniker: 'asset',
data: {
typeUrl: 'json',
value: {
key: 'value2',
sn: Math.random(),
},
},
wallet: seller,
},
{ conn: 'offer-chain' }
);
console.log('ensureSellerAsset', hash, address);
return address;
};
// ensure token for buyer on asset chain
const ensureBuyerToken = async () => {
const hash = await ForgeSDK.checkin({ wallet: buyer }, { conn: 'demand-chain' });
console.log('ensureSellerAsset', hash);
};
// setup swap on asset chain
const doBuyerSetup = async (asset, hashlock) => {
const hash = await ForgeSDK.setupSwap(
{
token: 10,
assets: [],
receiver: seller.toAddress(),
hashlock,
wallet: buyer,
},
{ conn: 'demand-chain' }
);
console.log('doBuyerSetup', hash);
return hash;
};
// setup swap on app chain
const doSellerSetup = async (asset, hashlock) => {
const hash = await ForgeSDK.setupSwap(
{
token: 0,
assets: [asset],
receiver: buyer.toAddress(),
hashlock,
wallet: seller,
},
{ conn: 'offer-chain' }
);
console.log('doSellerSetup', hash);
return hash;
};
// retrieve swap on app chain
const doBuyerRetrieve = async (address, hashkey) => {
const hash = await ForgeSDK.retrieveSwap(
{
address,
hashkey,
wallet: buyer,
},
{ conn: 'offer-chain' }
);
console.log('doBuyerRetrieve', hash);
};
// retrieve swap on asset chain
const doSellerRetrieve = async (address, hashkey) => {
const hash = await ForgeSDK.retrieveSwap(
{
address,
hashkey,
wallet: seller,
},
{ conn: 'demand-chain' }
);
console.log('doSellerRetrieve', hash);
};
// token and asset
const asset = await ensureSellerAsset();
console.log('asset', asset);
await ensureBuyerToken();
await sleep(3000);
// Setup swap by buyer
const hashkey = getRandomBytes(32);
const hashlock = Hasher.SHA3.hash256(hashkey);
const [buyerSetupHash, buyerSwapAddress] = await doBuyerSetup(asset, hashlock);
const [sellerSetupHash, sellerSwapAddress] = await doSellerSetup(asset, hashlock);
console.log('setup', {
hashkey,
hashlock,
buyerSetupHash,
buyerSwapAddress,
sellerSetupHash,
sellerSwapAddress,
});
await sleep(3000);
// Inspect swap
const buyerSwapState = await ForgeSDK.getSwapState(
{ address: buyerSwapAddress },
{ conn: 'demand-chain' }
);
const sellerSwapState = await ForgeSDK.getSwapState(
{ address: sellerSwapAddress },
{ conn: 'offer-chain' }
);
console.log('buyerSwapState', buyerSwapState);
console.log('sellerSwapState', sellerSwapState);
await doBuyerRetrieve(sellerSwapAddress, hashkey);
await doSellerRetrieve(buyerSwapAddress, hashkey);
} catch (err) {
console.error(err);
console.log(JSON.stringify(err.errors));
}
})();
用 Java SDK 做原子交换
TODO
用 Python SDK 做原子交换
TODO