## sign ``` sign(txJSON: string, secret: string, options: object): {signedTransaction: string, id: string} sign(txJSON: string, keypair: object, options: object): {signedTransaction: string, id: string} ``` Sign a prepared transaction. The signed transaction can then be [submitted](#submit). This method can sign any of [the transaction types supported by ripple-binary-codec](https://github.com/ripple/ripple-binary-codec/blob/cfcde79c19c359e9a0466d7bc3dc9a3aef47bb99/src/enums/definitions.json#L1637). When a new transaction type is added to the XRP Ledger, it is unrecognized until `ripple-binary-codec` is updated. If you try to sign an unrecognized transaction type, this method throws an error like the following: `Error: [TRANSACTION_TYPE] is not a valid name or ordinal for TransactionType` ### Parameters <%- renderSchema("input/sign.json") %> When this method is used for multi-signing, the `options` parameter is required. See the multi-signing example in this section for more details. ### Return Value This method returns an object with the following structure: <%- renderSchema("output/sign.json") %> ### Example ```javascript // AccountSet transaction that sets Domain to example.com: const txJSON = '{"Flags":2147483648,"TransactionType":"AccountSet","Account":"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59","Domain":"6578616D706C652E636F6D","LastLedgerSequence":8820051,"Fee":"12","Sequence":23}'; const secret = 'shsWGZcmZz6YsWWmcnpfr6fLTdtFV'; const keypair = { privateKey: '00ACCD3309DB14D1A4FC9B1DAE608031F4408C85C73EE05E035B7DC8B25840107A', publicKey: '02F89EAEC7667B30F33D0687BBA86C3FE2A08CCA40A9186C5BDE2DAA6FA97A37D8' }; return api.sign(txJSON, secret); // or: api.sign(txJSON, keypair); ``` <%- renderFixture("responses/sign.json") %> ### Example Keypairs To learn how keypairs are derived read [here](https://xrpl.org/cryptographic-keys.html#generating-keys). ```javascript // secp25519 (33 bytes) const privateKey = "002512BBDFDBB77510883B7DCCBEF270B86DEAC8B64AC762873D75A1BEE6298665" const publicKey = "0390A196799EE412284A5D80BF78C3E84CBB80E1437A0AECD9ADF94D7FEAAFA284" // ed25519 (Note the 0xED prefixes a 32 byte value for a total of 33 bytes) const privateKey = "ED0B6CBAC838DFE7F47EA1BD0DF00EC282FDF45510C92161072CCFB84035390C4D" const publicKey = "ED1A7C082846CFF58FF9A892BA4BA2593151CCF1DBA59F37714CC9ED39824AF85F" ``` ### Example (multi-signing) ```javascript const RippleAPI = require('ripple-lib').RippleAPI; // jon's address will have a multi-signing setup with a quorum of 2 const jon = { account: 'rJKpme4m2zBQceBuU89d7vLMzgoUw2Ptj', secret: 'sh4Va7b1wQof8knHFV2sxwX12fSgK' }; const aya = { account: 'rnrPdBjs98fFFfmRpL6hM7exT788SWQPFN', secret: 'snaMuMrXeVc2Vd4NYvHofeGNjgYoe' }; const bran = { account: 'rJ93RLnT1t5A8fCr7HTScw7WtfKJMRXodH', secret: 'shQtQ8Um5MS218yvEU3Ehy1eZQKqH' }; // Setup the signers list with a quorum of 2 const multiSignSetupTransaction = { "Flags": 0, "TransactionType": "SignerListSet", "Account": "rJKpme4m2zBQceBuU89d7vLMzgoUw2Ptj", "Fee": "120", "SignerQuorum": 2, "SignerEntries": [ { "SignerEntry": { "Account": "rnrPdBjs98fFFfmRpL6hM7exT788SWQPFN", "SignerWeight": 2 } }, { "SignerEntry": { "Account": "rJ93RLnT1t5A8fCr7HTScw7WtfKJMRXodH", "SignerWeight": 1 } }, ] }; // a transaction which requires multi signing const multiSignPaymentTransaction = { TransactionType: 'Payment', Account: 'rJKpme4m2zBQceBuU89d7vLMzgoUw2Ptj', Destination: 'rJ93RLnT1t5A8fCr7HTScw7WtfKJMRXodH', Amount: '88000000' }; const multiSignPaymentInstruction = { signersCount: 2 }; const api = new RippleAPI({ server: 'wss://s.altnet.rippletest.net:51233' }); api.connect().then(() => { // adding the multi signing feature to jon's account api.prepareTransaction(multiSignSetupTransaction).then((prepared) => { console.log(prepared); jonSign = api.sign(prepared.txJSON, jon.secret).signedTransaction; api.submit(jonSign).then( response => { console.log(response.resultCode, response.resultMessage); // multi sign a transaction api.prepareTransaction(multiSignPaymentTransaction, multiSignPaymentInstruction).then(prepared => { console.log(prepared); // Aya and Bran sign it too but with 'signAs' set to their own account let ayaSign = api.sign(prepared.txJSON, aya.secret, {'signAs': aya.account}).signedTransaction; let branSign = api.sign(prepared.txJSON, bran.secret, {'signAs': bran.account}).signedTransaction; // signatures are combined and submitted let combinedTx = api.combine([ayaSign, branSign]); api.submit(combinedTx.signedTransaction).then(response => { console.log(response.tx_json.hash); return api.disconnect(); }).catch(console.error); }).catch(console.error); }).catch(console.error) }).catch(console.error); }).catch(console.error); ``` If the multi-signing account was setup properly, the above example logs `resultCode: 'tesSUCCESS'` and the hash for the transaction. If any of `{signAs: some_address}` options were missing, the code returns a validation error such as: ``` [ValidationError(txJSON is not the same for all signedTransactions)] ```