Last active
May 29, 2022 10:02
-
-
Save daoka/aef3c428427676ab6fe03327c151dc01 to your computer and use it in GitHub Desktop.
Symbol SDK v3 Sandbox
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { SymbolFacade } = require('symbol-sdk').facade; | |
const { PrivateKey } = require('symbol-sdk/src/CryptoTypes'); | |
const { KeyPair } = require('symbol-sdk/src/symbol/KeyPair'); | |
const { Signature } = require('symbol-sdk/src/symbol/models'); | |
const axios = require('axios').default; | |
const wsl = require('ws'); | |
async function main() { | |
const facade = new SymbolFacade('testnet'); | |
// トランザクションをアナウンスするアカウントのキーペアを生成 | |
const alicePrivateKey = new PrivateKey('A************************************************C') | |
const aliceKeyPair = new KeyPair(alicePrivateKey); | |
const bobPubicKeyStr = '2******************************************************7'; | |
// トランザクションの有効期限を設定(6時間) | |
const now = Date.now(); | |
const eadj = 1637848847; | |
const deadline = BigInt(now - eadj*1000 + 60*60*6*1000); | |
// 埋め込みトランザクションの作成 | |
const embeddedTx1 = facade.transactionFactory.createEmbedded({ | |
type: 'transfer_transaction', | |
signerPublicKey: aliceKeyPair.publicKey.toString(), | |
recipientAddress: 'TD******************************RY', | |
mosaics: [ | |
{ mosaicId: 0x6BC3BF0D16883E5Fn, amount: 1n } | |
] | |
}); | |
const embeddedTx2 = facade.transactionFactory.createEmbedded({ | |
type: 'transfer_transaction', | |
signerPublicKey: bobPubicKeyStr, | |
recipientAddress: 'TC******************************GQ', | |
mosaics: [ | |
{ mosaicId: 0x3A8416DB2D53B6C8n, amount: 1000000n } | |
] | |
}); | |
// アグリゲートトランザクションの生成 | |
const embeddedTransactions = [embeddedTx1, embeddedTx2]; | |
const merkleHash = facade.constructor.hashEmbeddedTransactions(embeddedTransactions); | |
console.log(merkleHash.toString()); | |
const aggregateTx = facade.transactionFactory.create({ | |
type: 'aggregate_bonded_transaction', | |
signerPublicKey: aliceKeyPair.publicKey.toString(), | |
deadline: deadline, | |
transactionsHash: merkleHash, | |
transactions: embeddedTransactions, | |
}); | |
// アグリゲートトランザクションの手数料の設定 | |
// 後から署名が追加されるので、それを考慮して手数料計算をする | |
const feeMultiPlier = 100; | |
const signerNum = 2 | |
console.log(aggregateTx.size); | |
aggregateTx.fee.value = BigInt((aggregateTx.size + Signature.SIZE * signerNum) * feeMultiPlier ); | |
// アグリゲートトランザクションの署名 | |
const aggregateTxSignature = facade.signTransaction(aliceKeyPair, aggregateTx); | |
aggregateTx.signature = new Signature(aggregateTxSignature.bytes); | |
aggregateTx.network.generationHashSeed = facade.network; | |
const aggregateTxHash = facade.hashTransaction(aggregateTx); | |
console.log(aggregateTxHash.toString()); | |
// アグリゲートトランザクションのペイロードを生成 | |
const aggregatePayload = facade.transactionFactory.constructor.attachSignature(aggregateTx, aggregateTxSignature); | |
//console.log(aggregatePayload); | |
// ハッシュロックトランザクションの生成 | |
const hashLockTx = facade.transactionFactory.create({ | |
type: 'hash_lock_transaction', | |
signerPublicKey: aliceKeyPair.publicKey.toString(), | |
deadline: deadline, | |
hash: aggregateTxHash, | |
mosaic: { mosaicId: 0x3A8416DB2D53B6C8n, amount: 10000000n }, | |
duration: BigInt(2*2*60*24) | |
}); | |
// ハッシュロックトランザクションの手数料を設定 | |
hashLockTx.fee.value = BigInt(hashLockTx.size * feeMultiPlier); | |
// ハッシュロックトランザクションの署名 | |
const hashLockTxSignature = facade.signTransaction(aliceKeyPair, hashLockTx); | |
hashLockTx.signature = new Signature(hashLockTxSignature.bytes); | |
hashLockTx.network.generationHashSeed = facade.network; | |
const hashLockTxHash = facade.hashTransaction(hashLockTx); | |
console.log(hashLockTxHash.toString()); | |
// ハッシュロックトランザクションのペイロードを生成 | |
const hashLockPayload = facade.transactionFactory.constructor.attachSignature(hashLockTx, hashLockTxSignature); | |
const targetAddress = facade.network.publicKeyToAddress(aliceKeyPair.publicKey); | |
// トランザクションアナウンス後の状態監視のためのリスナーを生成 | |
const ws = new wsl.WebSocket('wss://sym-test.opening-line.jp:3001/ws'); | |
ws.on('open', () => { | |
console.log('connetion opened'); | |
}) | |
ws.on('close', () => { | |
console.log('connection closed'); | |
}) | |
ws.on('message', (msg) => { | |
const res = JSON.parse(msg); | |
if ('uid' in res) { | |
console.log(`uid : ${res.uid}`); | |
// ターゲットアドレスのトランザクションが承認されるの監視 | |
const confirmedBody = `{"uid": "${res.uid}", "subscribe": "confirmedAdded/${targetAddress}"}` | |
ws.send(confirmedBody); | |
// ターゲットアドレスの部分トランザクションが追加されるのを監視 | |
const partialBody = `{"uid": "${res.uid}", "subscribe": "partialAdded/${targetAddress}"}` | |
ws.send(partialBody); | |
// ターゲットアドレスのトランザクションがエラーになったのを監視 | |
const statusBody = `{"uid": "${res.uid}", "subscribe": "status/${targetAddress}"}` | |
ws.send(statusBody); | |
} | |
// トランザクションが承認されたときに発火 | |
if (res.topic === `confirmedAdded/${targetAddress}` && | |
res.data.meta.hash === hashLockTxHash.toString() | |
) { | |
// ハッシュロックトランザクションが承認されてから、`PUT /transactions/partial`で | |
// aggregate bounded transactionをアナウンスする | |
console.log('hashlock transaction confirmed'); | |
const rest = axios({ | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
method: 'put', | |
url: 'http://sym-test.opening-line.jp:3000/transactions/partial', | |
data: aggregatePayload, | |
}).then((r) => console.log(r.data)).catch((err) => console.log(err)); | |
} | |
// 部分トランザクションがキャッシュに追加されたときに発火 | |
if (res.topic === `partialAdded/${targetAddress}` && | |
res.data.meta.hash === aggregateTxHash.toString()) { | |
console.log('partial transaction added'); | |
console.log(res); | |
ws.close(); | |
} | |
// トランザクションがエラーになったときに発火 | |
if (res.topic === `status/${targetAddress}`) { | |
console.log(res.data.code); | |
ws.close(); | |
} | |
else { | |
console.log(res); | |
} | |
}); | |
// hashlock transactionをアナウンスする | |
try { | |
const res = await axios({ | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
method: 'put', | |
url: 'http://sym-test.opening-line.jp:3000/transactions', | |
data: hashLockPayload, | |
}); | |
console.log(res.data); | |
} catch(err) { | |
console.error(err); | |
} | |
} | |
main().then(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const { SymbolFacade } = require('symbol-sdk').facade; | |
const { PrivateKey } = require('symbol-sdk/src/CryptoTypes'); | |
const { KeyPair } = require('symbol-sdk/src/symbol/KeyPair'); | |
const { Signature } = require('symbol-sdk/src/symbol/models'); | |
const axios = require('axios').default; | |
const wsl = require('ws'); | |
async function main() { | |
// トランザクションをアナウンスするアカウントのキーペアを生成 | |
const privateKey = new PrivateKey('*********************************************************') | |
const keyPair = new KeyPair(privateKey); | |
// トランザクションの有効期限を設定(6時間) | |
const now = Date.now(); | |
const eadj = 1637848847; | |
const deadline = BigInt(now - eadj*1000 + 60*60*6*1000); | |
// 転送トランザクションのインスタンスを生成 | |
const facade = new SymbolFacade('testnet'); | |
const transaction = facade.transactionFactory.create({ | |
type: 'transfer_transaction', | |
signerPublicKey: keyPair.publicKey.toString(), | |
deadline: deadline, | |
recipientAddress: 'TB******************************Y', | |
mosaics: [ | |
{ mosaicId: 0x3A8416DB2D53B6C8n, amount: 1000000n } | |
] | |
}); | |
// 手数料率を設定 | |
const feeMultiPlier = 100; | |
transaction.fee.value = BigInt(transaction.size * feeMultiPlier); | |
// トランザクションを署名 | |
const signature = facade.signTransaction(keyPair, transaction); | |
// トランザクションのハッシュ値を算出 | |
transaction.signature = new Signature(signature.bytes); | |
transaction.network.generationHashSeed = facade.network | |
const hash = facade.hashTransaction(transaction); | |
console.log(hash.toString()); | |
// REST APIにアナウンスする用のペイロードを生成 | |
const jsonPayload = facade.transactionFactory.constructor.attachSignature(transaction, signature); | |
const targetAddress = facade.network.publicKeyToAddress(keyPair.publicKey); | |
console.log(targetAddress.toString()); | |
// トランザクションアナウンス後の状態監視のためのリスナーを生成 | |
const ws = new wsl.WebSocket('wss://sym-test.opening-line.jp:3001/ws'); | |
ws.on('open', () => { | |
console.log('connetion opened'); | |
}) | |
ws.on('close', () => { | |
console.log('connection closed'); | |
}) | |
ws.on('message', (msg) => { | |
const res = JSON.parse(msg); | |
if ('uid' in res) { | |
console.log(`uid : ${res.uid}`); | |
// ターゲットアドレスのトランザクションが承認されるの監視 | |
const confirmedBody = `{"uid": "${res.uid}", "subscribe": "confirmedAdded/${targetAddress}"}` | |
ws.send(confirmedBody); | |
// ターゲットアドレスのトランザクションがエラーになったのを監視 | |
const statusBody = `{"uid": "${res.uid}", "subscribe": "status/${targetAddress}"}` | |
ws.send(statusBody); | |
} | |
// トランザクションが承認されたときに発火 | |
if (res.topic === `confirmedAdded/${targetAddress}` && | |
res.data.meta.hash === hash.toString() | |
) { | |
console.log('transaction confirmed'); | |
ws.close(); | |
} | |
// トランザクションがエラーになったときに発火 | |
if (res.topic === `status/${targetAddress}` && | |
res.data.hash === hash.toString() | |
) { | |
console.log(res.data.code); | |
ws.close(); | |
} | |
else { | |
console.log(res); | |
} | |
}); | |
// トランザクションをアナウンスする | |
try { | |
const res = await axios({ | |
headers: { | |
'Content-Type': 'application/json' | |
}, | |
method: 'put', | |
url: 'http://sym-test.opening-line.jp:3000/transactions', | |
data: jsonPayload, | |
}); | |
console.log(res.data); | |
} catch(err) { | |
console.error(err); | |
} | |
} | |
main().then(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment