near-ca-test
Version:
An SDK for controlling Ethereum Accounts from a Near Account.
176 lines (175 loc) • 7.67 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NearEthAdapter = void 0;
const viem_1 = require("viem");
const __1 = require("..");
const beta_1 = require("../beta");
const request_1 = require("../utils/request");
class NearEthAdapter {
constructor(config) {
this.mpcContract = config.mpcContract;
this.derivationPath = config.derivationPath;
this.address = config.sender;
this.beta = new beta_1.Beta(this);
}
/**
* @returns Near accountId linked to derived ETH.
*/
nearAccountId() {
return this.mpcContract.connectedAccount.accountId;
}
/**
* Retrieves the balance of the Ethereum address associated with this adapter.
*
* @param {number} chainId - The chain ID of the Ethereum network to query.
* @returns {Promise<bigint>} - A promise that resolves to the balance of the address in wei.
*/
async getBalance(chainId) {
const network = __1.Network.fromChainId(chainId);
return network.client.getBalance({ address: this.address });
}
/**
* Constructs an EVM instance with the provided configuration.
* @param {AdapterParams} args - The configuration object for the Adapter instance.
*/
static async fromConfig(args) {
// Sender is uniquely determined by the derivation path!
const mpcContract = args.mpcContract;
const derivationPath = args.derivationPath || "ethereum,1";
return new NearEthAdapter({
sender: await mpcContract.deriveEthAddress(derivationPath),
derivationPath,
mpcContract,
});
}
/**
* Constructs an EVM instance with the provided configuration.
* @param {AdapterParams} args - The configuration object for the Adapter instance.
*/
static async mocked(args) {
// Sender is uniquely determined by the derivation path!
const mpcContract = args.mpcContract;
const derivationPath = args.derivationPath || "ethereum,1";
return new NearEthAdapter({
sender: await mpcContract.deriveEthAddress(derivationPath),
derivationPath,
mpcContract,
});
}
/**
* Takes a minimally declared Ethereum Transaction,
* builds the full transaction payload (with gas estimates, prices etc...),
* acquires signature from Near MPC Contract and submits transaction to public mempool.
*
* @param {BaseTx} txData - Minimal transaction data to be signed by Near MPC and executed on EVM.
* @param {bigint} nearGas - manually specified gas to be sent with signature request.
* Note that the signature request is a recursive function.
*/
async signAndSendTransaction(txData, nearGas) {
const { transaction, signArgs } = await this.createTxPayload(txData);
console.log(`Requesting signature from ${this.mpcContract.accountId()}`);
const signature = await this.mpcContract.requestSignature(signArgs, nearGas);
return (0, __1.broadcastSignedTransaction)({ transaction, signature });
}
/**
* Takes a minimally declared Ethereum Transaction,
* builds the full transaction payload (with gas estimates, prices etc...),
* acquires signature from Near MPC Contract and submits transaction to public mempool.
*
* @param {BaseTx} txData - Minimal transaction data to be signed by Near MPC and executed on EVM.
* @param {bigint} nearGas - manually specified gas to be sent with signature request.
* Note that the signature request is a recursive function.
*/
async getSignatureRequestPayload(txData, nearGas) {
const { transaction, signArgs } = await this.createTxPayload(txData);
return {
transaction,
requestPayload: await this.mpcContract.encodeSignatureRequestTx(signArgs, nearGas),
};
}
/**
* Builds a Near Transaction Payload for Signing serialized EVM Transaction.
* @param {Hex} transaction RLP encoded (i.e. serialized) Ethereum Transaction
* @param nearGas optional gas parameter
* @returns {FunctionCallTransaction<SignArgs>} Prepared Near Transaction with signerId as this.address
*/
async mpcSignRequest(transaction, nearGas) {
return this.mpcContract.encodeSignatureRequestTx({
payload: (0, __1.buildTxPayload)(transaction),
path: this.derivationPath,
key_version: 0,
}, nearGas);
}
/**
* Builds a complete, unsigned transaction (with nonce, gas estimates, current prices)
* and payload bytes in preparation to be relayed to Near MPC contract.
*
* @param {BaseTx} tx - Minimal transaction data to be signed by Near MPC and executed on EVM.
* @param {number?} nonce - Optional transaction nonce.
* @returns Transaction and its bytes (the payload to be signed on Near).
*/
async createTxPayload(tx) {
console.log(`Creating payload for sender: ${this.nearAccountId()} <> ${this.address}`);
const transaction = await this.buildTransaction(tx);
console.log("Built (unsigned) Transaction", transaction);
const signArgs = {
payload: (0, __1.buildTxPayload)(transaction),
path: this.derivationPath,
key_version: 0,
};
return { transaction, signArgs };
}
/**
* Transforms minimal transaction request data into a fully populated EVM transaction.
* @param {BaseTx} tx - Minimal transaction request data
* @returns {Hex} serialized (aka RLP encoded) transaction.
*/
async buildTransaction(tx) {
const transaction = await (0, __1.populateTx)(tx, this.address);
console.log("Transaction Request", transaction);
return (0, viem_1.serializeTransaction)(transaction);
}
// Below code is inspired by https://github.com/Connor-ETHSeoul/near-viem
async signTypedData(typedData) {
return this.sign((0, viem_1.hashTypedData)(typedData));
}
async signMessage(message) {
return this.sign((0, viem_1.hashMessage)(message));
}
/**
* Requests signature from Near MPC Contract.
* @param msgHash - Message Hash to be signed.
* @returns Two different potential signatures for the hash (one of which is valid).
*/
async sign(msgHash) {
const signature = await this.mpcContract.requestSignature({
path: this.derivationPath,
payload: (0, __1.toPayload)(msgHash),
key_version: 0,
});
return (0, viem_1.serializeSignature)(signature);
}
/**
* Encodes a signature request for submission to the Near-Ethereum transaction MPC contract.
*
* @async
* @function encodeSignRequest
* @param {SignRequestData} signRequest - The signature request data containing method, chain ID, and parameters.
* @returns {Promise<NearEthTxData>}
* - Returns a promise that resolves to an object containing the encoded Near-Ethereum transaction data,
* the original EVM message, and recovery data necessary for verifying or reconstructing the signature.
*/
async encodeSignRequest(signRequest) {
const { evmMessage, hashToSign } = await (0, request_1.requestRouter)(signRequest);
return {
nearPayload: await this.mpcContract.encodeSignatureRequestTx({
path: this.derivationPath,
payload: (0, __1.toPayload)(hashToSign),
key_version: 0,
}),
evmMessage,
hashToSign,
};
}
}
exports.NearEthAdapter = NearEthAdapter;