@infibridge/celo-sdk-base
Version:
EthersJS wrapper for Celo Blockchain. Based on https://github.com/celo-tools/celo-ethers-wrapper with small modifications.
184 lines • 15.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseCeloTransaction = exports.serializeCeloTransaction = exports.celoAllowedTransactionKeys = exports.celoTransactionFields = void 0;
const ethers_1 = require("ethers");
const logger = new ethers_1.utils.Logger('CeloTransactionsWrapper');
exports.celoTransactionFields = [
{ name: 'nonce', maxLength: 32, numeric: true },
{ name: 'gasPrice', maxLength: 32, numeric: true },
{ name: 'gasLimit', maxLength: 32, numeric: true },
{ name: 'feeCurrency', length: 20 },
{ name: 'gatewayFeeRecipient', length: 20 },
{ name: 'gatewayFee', maxLength: 32, numeric: true },
{ name: 'to', length: 20 },
{ name: 'value', maxLength: 32, numeric: true },
{ name: 'data' },
];
exports.celoAllowedTransactionKeys = {
chainId: true,
data: true,
gasLimit: true,
gasPrice: true,
nonce: true,
to: true,
value: true,
feeCurrency: true,
gatewayFeeRecipient: true,
gatewayFee: true,
};
// Almost identical to https://github.com/ethers-io/ethers.js/blob/master/packages/transactions/src.ts/index.ts#L85
// Need to override to use the celo tx prop whitelists above
function serializeCeloTransaction(transaction, signature) {
ethers_1.utils.checkProperties(transaction, exports.celoAllowedTransactionKeys);
const raw = [];
exports.celoTransactionFields.forEach(function (fieldInfo) {
let value = transaction[fieldInfo.name] || [];
const options = {};
if (fieldInfo.numeric) {
options.hexPad = 'left';
}
value = ethers_1.utils.arrayify(ethers_1.utils.hexlify(value, options));
// Fixed-width field
if (fieldInfo.length &&
value.length !== fieldInfo.length &&
value.length > 0) {
logger.throwArgumentError('invalid length for ' + fieldInfo.name, 'transaction:' + fieldInfo.name, value);
}
// Variable-width (with a maximum)
if (fieldInfo.maxLength) {
value = ethers_1.utils.stripZeros(value);
if (value.length > fieldInfo.maxLength) {
logger.throwArgumentError('invalid length for ' + fieldInfo.name, 'transaction:' + fieldInfo.name, value);
}
}
raw.push(ethers_1.utils.hexlify(value));
});
let chainId = 0;
if (transaction.chainId != null) {
// A chainId was provided; if non-zero we'll use EIP-155
chainId = transaction.chainId;
if (typeof chainId !== 'number') {
logger.throwArgumentError('invalid transaction.chainId', 'transaction', transaction);
}
}
else if (signature &&
!ethers_1.utils.isBytesLike(signature) &&
signature.v &&
signature.v > 28) {
// No chainId provided, but the signature is signing with EIP-155; derive chainId
chainId = Math.floor((signature.v - 35) / 2);
}
// We have an EIP-155 transaction (chainId was specified and non-zero)
if (chainId !== 0) {
raw.push(ethers_1.utils.hexlify(chainId)); // @TODO: hexValue?
raw.push('0x');
raw.push('0x');
}
// Requesting an unsigned transation
if (!signature) {
return ethers_1.utils.RLP.encode(raw);
}
// The splitSignature will ensure the transaction has a recoveryParam in the
// case that the signTransaction function only adds a v.
const sig = ethers_1.utils.splitSignature(signature);
// We pushed a chainId and null r, s on for hashing only; remove those
let v = 27 + sig.recoveryParam;
if (chainId !== 0) {
raw.pop();
raw.pop();
raw.pop();
v += chainId * 2 + 8;
// If an EIP-155 v (directly or indirectly; maybe _vs) was provided, check it!
if (sig.v > 28 && sig.v !== v) {
logger.throwArgumentError('transaction.chainId/signature.v mismatch', 'signature', signature);
}
}
else if (sig.v !== v) {
logger.throwArgumentError('transaction.chainId/signature.v mismatch', 'signature', signature);
}
raw.push(ethers_1.utils.hexlify(v));
raw.push(ethers_1.utils.stripZeros(ethers_1.utils.arrayify(sig.r)));
raw.push(ethers_1.utils.stripZeros(ethers_1.utils.arrayify(sig.s)));
return ethers_1.utils.RLP.encode(raw);
}
exports.serializeCeloTransaction = serializeCeloTransaction;
// Almost identical to https://github.com/ethers-io/ethers.js/blob/master/packages/transactions/src.ts/index.ts#L165
// Need to override to use the celo tx prop whitelists above
function parseCeloTransaction(rawTransaction) {
const transaction = ethers_1.utils.RLP.decode(rawTransaction);
if (transaction.length !== 12 && transaction.length !== 9) {
logger.throwArgumentError('invalid raw transaction', 'rawTransaction', rawTransaction);
}
const tx = {
nonce: handleNumber(transaction[0]).toNumber(),
gasPrice: handleNumber(transaction[1]),
gasLimit: handleNumber(transaction[2]),
feeCurrency: handleAddress(transaction[3]),
gatewayFeeRecipient: handleAddress(transaction[4]),
gatewayFee: handleNumber(transaction[5]),
to: handleAddress(transaction[6]),
value: handleNumber(transaction[7]),
data: transaction[8],
chainId: 0,
};
// Legacy unsigned transaction
if (transaction.length === 9) {
return tx;
}
try {
tx.v = ethers_1.BigNumber.from(transaction[9]).toNumber();
}
catch (error) {
console.log(error);
return tx;
}
tx.r = ethers_1.utils.hexZeroPad(transaction[10], 32);
tx.s = ethers_1.utils.hexZeroPad(transaction[11], 32);
if (ethers_1.BigNumber.from(tx.r).isZero() && ethers_1.BigNumber.from(tx.s).isZero()) {
// EIP-155 unsigned transaction
tx.chainId = tx.v;
tx.v = 0;
}
else {
// Signed Tranasaction
tx.chainId = Math.floor((tx.v - 35) / 2);
if (tx.chainId < 0) {
tx.chainId = 0;
}
let recoveryParam = tx.v - 27;
const raw = transaction.slice(0, 6);
if (tx.chainId !== 0) {
raw.push(ethers_1.utils.hexlify(tx.chainId));
raw.push('0x');
raw.push('0x');
recoveryParam -= tx.chainId * 2 + 8;
}
const digest = ethers_1.utils.keccak256(ethers_1.utils.RLP.encode(raw));
try {
tx.from = ethers_1.utils.recoverAddress(digest, {
r: ethers_1.utils.hexlify(tx.r),
s: ethers_1.utils.hexlify(tx.s),
recoveryParam: recoveryParam,
});
}
catch (error) {
console.log(error);
}
tx.hash = ethers_1.utils.keccak256(rawTransaction);
}
return tx;
}
exports.parseCeloTransaction = parseCeloTransaction;
function handleAddress(value) {
if (value === '0x') {
return undefined;
}
return ethers_1.utils.getAddress(value);
}
function handleNumber(value) {
if (value === '0x') {
return ethers_1.constants.Zero;
}
return ethers_1.BigNumber.from(value);
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2Vsb1RyYW5zYWN0aW9uc1dyYXBwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvQ2Vsb1RyYW5zYWN0aW9uc1dyYXBwZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsbUNBUWU7QUFjZixNQUFNLE1BQU0sR0FBRyxJQUFJLGNBQUssQ0FBQyxNQUFNLENBQUMseUJBQXlCLENBQUMsQ0FBQTtBQWM3QyxRQUFBLHFCQUFxQixHQUFHO0lBQ2pDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUU7SUFDL0MsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRTtJQUNsRCxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFO0lBQ2xELEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFO0lBQ25DLEVBQUUsSUFBSSxFQUFFLHFCQUFxQixFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUU7SUFDM0MsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRTtJQUNwRCxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRTtJQUMxQixFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFO0lBQy9DLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRTtDQUNuQixDQUFBO0FBRVksUUFBQSwwQkFBMEIsR0FBK0I7SUFDbEUsT0FBTyxFQUFFLElBQUk7SUFDYixJQUFJLEVBQUUsSUFBSTtJQUNWLFFBQVEsRUFBRSxJQUFJO0lBQ2QsUUFBUSxFQUFFLElBQUk7SUFDZCxL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