The weight is 1 per sign and weight needed is 3, meaning all signers have to sign to execute a transaction.
Vscode is needed with npm in this example. This video shows you how to install vscode and npm: https://www.youtube.com/watch?v=Xit4miSByOw
Install the xrpl package with npm i xrpl@latest
To set up the wallet itself, create this file:
multisig.js
Code: Select all
const xrpl = require("xrpl")
async function main() {
const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233") //use whatever network you use here
await client.connect()
const masterSeed = "masterseedhere" //start with s
const masterWallet = xrpl.Wallet.fromSeed(masterSeed)
console.log("Master Wallet Address:", masterWallet.address)
const signer1 = xrpl.Wallet.fromSeed("signerseed1") //starts with s
const signer2 = xrpl.Wallet.fromSeed("signerseed2") //starts with s
const signer3 = xrpl.Wallet.fromSeed("signerseed3") //starts with s
console.log("Signer1:", signer1.address)
console.log("Signer2:", signer2.address)
console.log("Signer3:", signer3.address)
const signerListTx = {
TransactionType: "SignerListSet",
Account: masterWallet.address,
SignerQuorum: 3,
SignerEntries: [
{ SignerEntry: { Account: signer1.address, SignerWeight: 1 } },
{ SignerEntry: { Account: signer2.address, SignerWeight: 1 } },
{ SignerEntry: { Account: signer3.address, SignerWeight: 1 } },
],
}
const prepared = await client.autofill(signerListTx)
const signed = masterWallet.sign(prepared)
const result = await client.submitAndWait(signed.tx_blob)
console.log("Raw result:", JSON.stringify(result, null, 2))
console.log("Transaction result:", result.result.engine_result)
await client.disconnect()
}
main()
You can still use your wallet after this, to make sure you can't, you need to disable your masterkey. That is a smart thing to do once you go live.
Now let me show you two examples, one is showing how to add a trustline, the other one is showing how to send a payment.
To set a trustline, first create the file
set-trustline-multisign-prepare.js
Code: Select all
const fs = require("fs")
const xrpl = require("xrpl")
async function main() {
const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233")
await client.connect()
const master = xrpl.Wallet.fromSeed("masterseed here")
const trustSetTx = {
TransactionType: "TrustSet",
Account: master.address,
LimitAmount: {
currency: "524C555344000000000000000000000000000000", //in this example set a random testnet asset
issuer: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", //in this example set a random testnet asset
value: "1000000000"
}
}
const prepared = await client.autofill(trustSetTx, { fee_mult_max: 4 })
prepared.Fee = (parseInt(prepared.Fee, 10) * 20).toString()
prepared.LastLedgerSequence = prepared.LastLedgerSequence + 100
fs.writeFileSync("prepared_tx.json", JSON.stringify(prepared, null, 2))
console.log("Prepared TX saved to prepared_tx.json")
await client.disconnect()
}
main()
Create three files now (set-trustline-sign-1.js set-trustline-sign-2.js and set-trustline-sign-3.js) These files are all identical, but they will each have their own secret seed (signer one two and three)
Code: Select all
const fs = require("fs")
const xrpl = require("xrpl")
async function main() {
const prepared = JSON.parse(fs.readFileSync("prepared_tx.json"))
const signer1 = xrpl.Wallet.fromSeed("the signers secret seeds") //add the secret seed for each signer
const signed = signer1.sign(prepared, true)
fs.writeFileSync("signer1_blob.json", JSON.stringify(signed, null, 2))
console.log("signer1_blob.json written with tx_blob")
}
main()
Do so by typing
node set-trustline-sign-1.js
node set-trustline-sign-2.js
node set-trustline-sign-3.js
These will each create a file, signer1-3_blob.json. The blobs contains signatures that are valid until the last ledger sequence has passed by.
We will now submit the blobs to the xrpledger.
submit-trustline-set.js
Code: Select all
const fs = require("fs")
const xrpl = require("xrpl")
async function main() {
const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233")
await client.connect()
const sig1 = JSON.parse(fs.readFileSync("signer1_blob.json"))
const sig2 = JSON.parse(fs.readFileSync("signer2_blob.json"))
const sig3 = JSON.parse(fs.readFileSync("signer3_blob.json"))
const blobs = [sig1.tx_blob, sig2.tx_blob, sig3.tx_blob]
const multisigned = xrpl.multisign(blobs)
console.log("Multisigned blob:", multisigned)
const result = await client.submitAndWait(multisigned)
console.log("Raw submit result:", JSON.stringify(result, null, 2))
if (result.result?.tx_json?.hash) {
const txHash = result.result.tx_json.hash
const txResponse = await client.request({
command: "tx",
transaction: txHash
})
console.log("Transaction lookup:", JSON.stringify(txResponse, null, 2))
}
await client.disconnect()
}
main()
Now, lets prepare a payment.
payment-prepare.js
Code: Select all
const fs = require("fs")
const xrpl = require("xrpl")
async function main() {
const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233")
await client.connect()
const sender = xrpl.Wallet.fromSeed("the master seed") // multisigned wallet
const paymentTx = {
TransactionType: "Payment",
Account: sender.address,
Destination: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", //a random receiver
//Amount: "1000000" // If you use it for xrp, use it this way (counted in drops in this particular example, that is not always the thing).
Amount: {
currency: "524C555344000000000000000000000000000000", // a currency we got a trustline for
issuer: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", //a currency we got a trustline for
value: "1" // when sending other currencies and not xrp, they are not counted in drops, this is 1 unit of the currency being sent
}
}
const prepared = await client.autofill(paymentTx, { fee_mult_max: 4 })
prepared.Fee = (parseInt(prepared.Fee, 10) * 20).toString()
prepared.LastLedgerSequence = prepared.LastLedgerSequence + 100
fs.writeFileSync("prepared_payment.json", JSON.stringify(prepared, null, 2))
console.log("Prepared payment saved to prepared_payment.json")
await client.disconnect()
}
main()
Create 3 files, set-payment-sign-1.js, set-payment-sign-2.js and set-payment-sign-3.js
Code: Select all
const fs = require("fs")
const xrpl = require("xrpl")
async function main() {
const prepared = JSON.parse(fs.readFileSync("prepared_payment.json"))
const signer1 = xrpl.Wallet.fromSeed("signer seed") //add the signer seeds here
const signed = signer1.sign(prepared, true)
fs.writeFileSync("signer1_payment.json", JSON.stringify(signed, null, 2))
console.log("signer1_payment.json written with tx_blob")
}
main()
node set-payment-sign-1.js
node set-payment-sign-2.js
node set-payment-sign-3.js
You will then have your blobs, after that we will just submit the payment.
submit-payment.js
Code: Select all
const fs = require("fs")
const xrpl = require("xrpl")
async function main() {
const client = new xrpl.Client("wss://s.altnet.rippletest.net:51233")
await client.connect()
const sig1 = JSON.parse(fs.readFileSync("signer1_payment.json"))
const sig2 = JSON.parse(fs.readFileSync("signer2_payment.json"))
const sig3 = JSON.parse(fs.readFileSync("signer3_payment.json"))
const multisigned = xrpl.multisign([sig1.tx_blob, sig2.tx_blob, sig3.tx_blob])
console.log("Multisigned blob:", multisigned)
const result = await client.submitAndWait(multisigned)
console.log("Payment result:", JSON.stringify(result, null, 2))
await client.disconnect()
}
main()