UNPKG

@ngraveio/ur-sync

Version:

Provides BC-UR types for syncing multiple coins and accounts from cold wallets to watch only wallets.

172 lines (168 loc) 7.04 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DetailedAccount = void 0; const bc_ur_1 = require("@ngraveio/bc-ur"); const ur_blockchain_commons_1 = require("@ngraveio/ur-blockchain-commons"); const ur_hex_string_1 = require("@ngraveio/ur-hex-string"); class DetailedAccount extends (0, bc_ur_1.registryItemFactory)({ tag: 41402, URType: 'detailed-account', keyMap: { account: 1, tokenIds: 2, }, allowKeysNotInMap: false, CDDL: ` account_exp = #6.40303(hdkey) / #6.40308(output-descriptor) ; Accounts are specified using either '#6.40303(hdkey)' or ; '#6.40308(output-descriptor)'. ; By default, '#6.40303(hdkey)' should be used to share public keys and ; extended public keys. ; '#6.308(output-descriptor)' should be used to share an output descriptor, ; e.g. for the different Bitcoin address formats (P2PKH, P2SH-P2WPKH, P2WPKH, P2TR). ; Optional 'token-ids' to indicate the synchronization of a list of tokens with ; the associated accounts ; 'token-id' is defined differently depending on the blockchain: ; - ERC20 tokens on EVM chains are identified by their contract addresses ; (e.g. "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48") ; - ERC1155 tokens are identifed with their contract addresses followed by their ; ID with ':' as separator (e.g. "0xfaafdc07907ff5120a76b34b731b278c38d6043c: ; 508851954656174721695133294256171964208") ; - ESDT tokens on MultiversX are by their name followed by their ID with "-" as ; separator (e.g. "USDC-c76f1f") ; - SPL tokens on Solana are identified by their contract addresses ; (e.g. "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v") detailed-account = { account: account_exp, ? token-ids: [+ string / bytes] ; Specify multiple tokens associated to one account } account = 1 token-ids = 2 `, }) { constructor(data) { // Token Ids are just hex string for erc20 token like 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 // For ESDT and SPL types its going to be encoded as string // We will try to parse the string into bytes with removing 0x part, // if we cannot we will encode it as utf8 string super(data); this.getAccount = () => this.data.account; this.getHdKey = () => { return this.data.account instanceof ur_blockchain_commons_1.HDKey ? this.data.account : undefined; }; this.getOutputDescriptor = () => { return this.data.account instanceof ur_blockchain_commons_1.OutputDescriptor ? this.data.account : undefined; }; this.getTokenIds = () => { if (!this.data.tokenIds) return undefined; // Always return string representation of the token ids return this.data.tokenIds.map((tokenId) => { if (tokenId instanceof ur_hex_string_1.HexString) { // Shall we really add 0x to start? return '0x' + tokenId.getData(); } return tokenId; }); }; //@ts-ignore this.data = data; let tokenIds = data.tokenIds; // If token ids are provided, convert them to hex strings if (tokenIds !== undefined && Array.isArray(data.tokenIds)) { // Try to parse them into hex strings tokenIds = tokenIds.map(tokenId => { // If its already hexstring, return it if (tokenId instanceof ur_hex_string_1.HexString) return tokenId; // If its buffer or a string try to parse as HexString try { return new ur_hex_string_1.HexString(tokenId); } catch (error) { /* no-op */ return tokenId; } }); //@ts-ignore this.data.tokenIds = tokenIds; } } verifyInput(input) { const errors = []; // Checks for the accounts if (!input.account) { errors.push(new Error('Account must be provided')); } else { try { DetailedAccount.checkAccount(input.account); } catch (error) { errors.push(error); } } // Checks for the token ids if (input.tokenIds !== undefined) { // Token ids must be an array if (!Array.isArray(input.tokenIds)) { errors.push(new Error('Token ids must be an array')); } else { // Token ids must be either string or uint8array (Buffer is also Uint8Array) input.tokenIds.forEach(tokenId => { if (typeof tokenId !== 'string' && !(tokenId instanceof Uint8Array) && !(tokenId instanceof ur_hex_string_1.HexString)) { errors.push(new Error('Token id must be either a string or a Uint8Array or HexString')); } }); } } return { valid: errors.length === 0, reasons: errors.length > 0 ? errors : undefined, }; } static checkAccount(account) { // If account is HDKey, check if it has origin and a valid path if (account instanceof ur_blockchain_commons_1.HDKey) { return DetailedAccount.checkHdKey(account); } else if (account instanceof ur_blockchain_commons_1.OutputDescriptor) { return DetailedAccount.checkOutputDescriptor(account); } else { throw new Error('Account must be instance of HDKey or OutputDescriptor'); } return true; } static checkOutputDescriptor(account) { // For the output descriptor, it must have only 1 key and it must be HDKey const keys = account.data.keys; if (!keys || keys.length !== 1) { throw new Error('Output descriptor must have only 1 key'); } const key = keys[0]; if (!(key instanceof ur_blockchain_commons_1.HDKey)) { throw new Error('Output descriptor key must be instance of HDKey'); } // Check HDKey properties return DetailedAccount.checkHdKey(key); } static checkHdKey(hdKey) { const origin = hdKey.getOrigin(); if (origin == undefined) { throw new Error('HDKey must have origin'); } // Now for detailed account we must have only 1 path // and it should only contain simple path components // Eg: m/44'/60'/0 // The other path components are not allowed // Eg: m/44/*/1-5 if (!origin.isOnlySimple()) { throw new Error('Detailed account path can only contain index components'); } return true; } } exports.DetailedAccount = DetailedAccount; //# sourceMappingURL=DetailedAccount.js.map