UNPKG

@coolwallet/sol

Version:
136 lines (117 loc) 4.37 kB
import base58 from 'bs58'; import BN from 'bn.js'; import * as types from '../config/types'; import { ComputeBudgetInstruction } from '../config/types'; const HEX_REGEX = /[0-9A-Fa-f]{6}/g; export const isBase58Format = (value?: string): boolean => { if (!value) return false; return /^[A-HJ-NP-Za-km-z1-9]*$/.test(value); }; function isHexFormat(value: string): boolean { const match = value.match(HEX_REGEX); return !!match; } export function toBase58(publicKey: types.Address): string { if (typeof publicKey === 'string') { if (isBase58Format(publicKey)) return publicKey; if (isHexFormat(publicKey)) return base58.encode(Buffer.from(publicKey, 'hex')); return publicKey; } return base58.encode(publicKey); } export function toBase58Buffer(publicKey: types.Address): Buffer { if (typeof publicKey === 'string') { if (isBase58Format(publicKey)) return base58.decode(publicKey); if (isHexFormat(publicKey)) return Buffer.from(publicKey, 'hex'); return Buffer.from(publicKey); } return publicKey; } export function toPublicKey(publicKey: string | Buffer): string { if (typeof publicKey === 'string') return publicKey; return base58.encode(publicKey); } export function pubKeyToAddress(publicKey: string): string { const pubKeyBuf = Buffer.from(publicKey, 'hex'); return base58.encode(pubKeyBuf); } /** * CW-21334 Fixed user's publicKey just matches the base58 encoding, resulting in repeated decoding. * * The user's Solana address (base58 encoded) is: * 5XZiuCyozesbRJsSdoJQCTHQRnTGDfSms5bV1ybLn9yg * * After converting it to Hex: * fc238b62abd32cd576f1d5568d3b6b5cb2fbc57b419cc2b4cd8a2814973919a7 * This hex conform to the Base58 format (without 0, O, i, I, +, /), causing base58.decode to be executed again, resulting in an incorrect publicKey. * * How to fix it: * Adjust base58 verification method. A 32-byte public key can only be base58 encoded using 43 or 44 characters. */ export const formHex = (address: string | Buffer | undefined): string => { if (!address) return ''; if (typeof address === 'string') { if (isBase58Format(address)) return base58.decode(address).toString('hex'); return address; } return address.toString('hex'); }; export const numberToStringHex = (value: number | number[], pad: number): string => Buffer.from(typeof value === 'number' ? [value] : value) .toString('hex') .padStart(pad, '0'); export const encodeLength = (bytes: number[], len: number): void => { let rem_len = len; for (;;) { let elem = rem_len & 0x7f; rem_len >>= 7; if (rem_len == 0) { bytes.push(elem); break; } else { elem |= 0x80; bytes.push(elem); } } }; export function toReverseUintBuffer(numberOrString: number | string, byteSize: number): Buffer { const bn = new BN(numberOrString); const buf = Buffer.from(bn.toArray()).reverse(); return Buffer.alloc(byteSize).fill(buf, 0, buf.length); } export function toUintBuffer(numberOrString: number | string, byteSize: number): Buffer { const bn = new BN(numberOrString); const buf = Buffer.from(bn.toArray()); return Buffer.alloc(byteSize).fill(buf, byteSize - buf.length, byteSize); } export function computeBudgetEncode(type: ComputeBudgetInstruction, amount: number | string): Buffer { let data; let length; switch (type) { case ComputeBudgetInstruction.SetComputeUnitLimit: data = Buffer.alloc(5); length = 4; break; case ComputeBudgetInstruction.SetComputeUnitPrice: data = Buffer.alloc(9); length = 8; break; default: throw new Error('Not supported ComputeBudgetInstruction type: ' + type); } const typeSpan = 1; data.writeUIntLE(type, 0, typeSpan); const valueBuf = toReverseUintBuffer(amount, length); data.write(valueBuf.toString('hex'), typeSpan, length, 'hex'); return data; } export function splDataEncode(amount: number | string, tokenDecimals: number | string): Buffer { const data = Buffer.alloc(10); const programIdIndexSpan = 1; data.writeUIntLE(types.TokenInstruction.TransferChecked, 0, programIdIndexSpan); const valueHex = new BN(amount).toString(16, 8 * 2); const valueBuf = Buffer.from(valueHex, 'hex').reverse(); data.write(valueBuf.toString('hex'), programIdIndexSpan, 8, 'hex'); data.writeUInt8(+tokenDecimals, 9); return data; }