mirror of
https://github.com/XRPLF/xrpl-dev-portal.git
synced 2025-11-04 20:05:50 +00:00
130 lines
5.3 KiB
JavaScript
130 lines
5.3 KiB
JavaScript
if (typeof module !== "undefined") {
|
||
// Use var here because const/let are block-scoped to the if statement.
|
||
var xrpl = require('xrpl')
|
||
}
|
||
// List which Tickets are outstanding against one’s own account and use Tickets to collect signatures for multisign transactions
|
||
// https://xrpl.org/use-tickets.html
|
||
// https://xrpl.org/signerlistset.html#signerlistset
|
||
// https://xrpl.org/multi-signing.html#multi-signing
|
||
|
||
async function main() {
|
||
// Connect to a testnet node
|
||
console.log("Connecting to Testnet...")
|
||
const client = new xrpl.Client('wss://s.altnet.rippletest.net:51233')
|
||
await client.connect()
|
||
|
||
// Get account credentials from the Testnet Faucet
|
||
console.log("Requesting account credentials from the Testnet faucet, this may take awhile...")
|
||
const { wallet: main_wallet } = await client.fundWallet()
|
||
|
||
// Signer keys don't need to be funded on the ledger, it only needs to be cryptographically valid
|
||
// Thus, we could generate keys and set them as signers without the need to fund their accounts
|
||
// But we'll still fund them for testing purposes...
|
||
const { wallet: wallet_1 } = await client.fundWallet()
|
||
const { wallet: wallet_2 } = await client.fundWallet()
|
||
const { wallet: wallet_3 } = await client.fundWallet()
|
||
|
||
console.log(" Main Account: ", main_wallet.address)
|
||
console.log(" Seed: ", main_wallet.seed)
|
||
|
||
console.log("\n Signer 1: ", wallet_1.address)
|
||
console.log(" Signer 2: ", wallet_2.address)
|
||
console.log(" Signer 3: ", wallet_3.address)
|
||
|
||
// Send SignerListSet transaction
|
||
// Since each signer is given a signer weight of 1 and there are 3 signers, the maximum quorom would be 3
|
||
// SignerQuorom is a target number for the signer weights
|
||
// A multisig from this list is valid only if the sum weights of the signatures provided is greater than or equal to the SignerQuorom
|
||
const signerLiSetSignerList_tx = {
|
||
TransactionType: "SignerListSet",
|
||
Account: main_wallet.classicAddress,
|
||
SignerEntries: [
|
||
{
|
||
SignerEntry: {
|
||
Account: wallet_1.classicAddress,
|
||
SignerWeight: 1,
|
||
},
|
||
},
|
||
{
|
||
SignerEntry: {
|
||
Account: wallet_2.classicAddress,
|
||
SignerWeight: 1,
|
||
},
|
||
},
|
||
{
|
||
SignerEntry: {
|
||
Account: wallet_3.classicAddress,
|
||
SignerWeight: 1,
|
||
},
|
||
}
|
||
],
|
||
SignerQuorum: 2,
|
||
}
|
||
|
||
const signerLiSetSignerList_tx_prepared = await client.autofill(signerLiSetSignerList_tx)
|
||
const SetSignerList_tx_signed = main_wallet.sign(signerLiSetSignerList_tx_prepared)
|
||
console.log(`\n SignerListSet Tx hash: ${SetSignerList_tx_signed.hash}`)
|
||
|
||
const setsignerlist_submit = await client.submitAndWait(SetSignerList_tx_signed.tx_blob)
|
||
console.log(`\t Submit result: ${setsignerlist_submit.result.meta.TransactionResult}`)
|
||
|
||
const CreateTicket_tx = await client.autofill({
|
||
TransactionType: "TicketCreate",
|
||
Account: main_wallet.address,
|
||
TicketCount: 3
|
||
})
|
||
|
||
const CreateTicket_tx_signed = main_wallet.sign(CreateTicket_tx)
|
||
console.log("\n CreateTicket Tx hash:", CreateTicket_tx_signed.hash)
|
||
|
||
const ticket_submit = await client.submitAndWait(CreateTicket_tx_signed.tx_blob)
|
||
console.log(" Submit result:", ticket_submit.result.meta.TransactionResult)
|
||
|
||
const ticket_response = await client.request({
|
||
command: "account_objects",
|
||
account: main_wallet.address,
|
||
ledger_index: "validated",
|
||
type: "ticket"
|
||
})
|
||
|
||
console.log(`\n- Tickets issued by ${main_wallet.address}:\n`)
|
||
for (let i = 0; i < ticket_response.result.account_objects.length; i++) {
|
||
console.log(`Ticket ${i+1}: ${ticket_response.result.account_objects[i].TicketSequence}`)
|
||
}
|
||
|
||
// We'll use this ticket on our tx
|
||
const ticket_1 = ticket_response.result.account_objects[0].TicketSequence
|
||
|
||
console.log(`\n Ticket sequence ${ticket_1} will be used for our multi-sig transaction`)
|
||
|
||
const Payment_tx = {
|
||
"TransactionType": "AccountSet",
|
||
"Account": main_wallet.address,
|
||
"TicketSequence": ticket_1,
|
||
"LastLedgerSequence": null,
|
||
"Sequence": 0
|
||
}
|
||
|
||
const Payment_tx_prepared = await client.autofill(Payment_tx, signersCount=3)
|
||
|
||
// Each signer will sign the prepared tx (AccountSet_tx) and their signatures will be combines into 1 multi-sig transaction
|
||
const { tx_blob: Payment_tx_signed_1 } = wallet_1.sign(Payment_tx_prepared, multisign=true)
|
||
const { tx_blob: Payment_tx_signed_2 } = wallet_2.sign(Payment_tx_prepared, multisign=true)
|
||
const { tx_blob: Payment_tx_signed_3 } = wallet_3.sign(Payment_tx_prepared, multisign=true)
|
||
|
||
console.log("\n All signers have signed the transaction with their corresponding keys")
|
||
|
||
// Combine 3 of the signers' signatures to form a multi-sig transaction
|
||
const multisignedTx = xrpl.multisign([Payment_tx_signed_1, Payment_tx_signed_2, Payment_tx_signed_3])
|
||
|
||
const multisig_submit = await client.submitAndWait(multisignedTx)
|
||
console.log("\n Multi-sig Submit result:", multisig_submit.result.meta.TransactionResult)
|
||
console.log("\n Multi-sig Tx Binary:", multisignedTx)
|
||
|
||
client.disconnect()
|
||
|
||
// End main()
|
||
}
|
||
|
||
main()
|