Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to TSDoc (from JSDoc) #163

Merged
merged 1 commit into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion src/beta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,39 @@ import { isSignMethod, NearEncodedSignRequest, signMethods } from "./types";
import { NearEthAdapter } from "./chains/ethereum";
import { requestRouter } from "./utils/request";

/**
* Removes the EIP-155 prefix from an address string
*
* @param eip155Address - The EIP-155 formatted address
* @returns The address without the EIP-155 prefix
*/
function stripEip155Prefix(eip155Address: string): string {
return eip155Address.split(":").pop() ?? "";
}

/**
* Features currently underdevelopment that will be migrated into the adapter class once refined.
* Features currently under development that will be migrated into the adapter class once refined.
* These features are accessible through the adapter class as `adapter.beta.methodName(...)`
*/
export class Beta {
adapter: NearEthAdapter;

/**
* Creates a new Beta instance
*
* @param adapter - The NearEthAdapter instance to use
*/
constructor(adapter: NearEthAdapter) {
this.adapter = adapter;
}

/**
* Handles a WalletConnect session request by encoding it for NEAR
*
* @param request - The WalletConnect session request
* @returns The encoded request for NEAR
* @throws Error if the sign method is not supported
*/
async handleSessionRequest(
request: Partial<WalletKitTypes.SessionRequest>
): Promise<NearEncodedSignRequest> {
Expand Down Expand Up @@ -52,6 +70,13 @@ export class Beta {
};
}

/**
* Responds to a session request with a signature
*
* @param signature - The signature to respond with
* @param transaction - Optional transaction hex
* @returns The serialized signature or transaction hash
*/
async respondSessionRequest(
signature: Signature,
transaction?: Hex
Expand Down
101 changes: 59 additions & 42 deletions src/chains/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import { Beta } from "../beta";
import { requestRouter } from "../utils/request";
import { Account } from "near-api-js";

/**
* Adapter class for interacting with Ethereum through NEAR MPC contract
*/
export class NearEthAdapter {
readonly mpcContract: IMpcContract;
readonly address: Address;
Expand All @@ -47,36 +50,41 @@ export class NearEthAdapter {
}

/**
* @returns Near Account linked to derived EVM account.
* Gets the NEAR Account linked to derived EVM account
*
* @returns The connected NEAR Account
*/
nearAccount(): Account {
return this.mpcContract.connectedAccount;
}

/**
* @returns Near accountId linked to derived EVM account.
* Gets the NEAR account ID linked to derived EVM account
*
* @returns The connected NEAR account ID
*/
nearAccountId(): string {
return this.mpcContract.connectedAccount.accountId;
}

/**
* Retrieves the balance of the Ethereum address associated with this adapter.
* 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.
* @param chainId - The chain ID of the Ethereum network to query
* @returns The balance of the address in wei
*/
async getBalance(chainId: number): Promise<bigint> {
const network = 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.
* Constructs an EVM instance with the provided configuration
*
* @param args - The configuration object for the Adapter instance
* @returns A new NearEthAdapter instance
*/
static async fromConfig(args: AdapterParams): Promise<NearEthAdapter> {
// Sender is uniquely determined by the derivation path!
const mpcContract = args.mpcContract;
const derivationPath = args.derivationPath || "ethereum,1";
return new NearEthAdapter({
Expand All @@ -87,11 +95,12 @@ export class NearEthAdapter {
}

/**
* Constructs an EVM instance with the provided configuration.
* @param {AdapterParams} args - The configuration object for the Adapter instance.
* Creates a mocked EVM instance with the provided configuration
*
* @param args - The configuration object for the Adapter instance
* @returns A new mocked NearEthAdapter instance
*/
static async mocked(args: AdapterParams): Promise<NearEthAdapter> {
// Sender is uniquely determined by the derivation path!
const mpcContract = args.mpcContract;
const derivationPath = args.derivationPath || "ethereum,1";
return new NearEthAdapter({
Expand All @@ -104,11 +113,11 @@ export class NearEthAdapter {
/**
* 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.
* 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.
* @param txData - Minimal transaction data to be signed by Near MPC and executed on EVM
* @param nearGas - Manually specified gas to be sent with signature request
* @returns The ethereum transaction hash
*/
async signAndSendTransaction(
txData: BaseTx,
Expand All @@ -125,11 +134,11 @@ export class NearEthAdapter {
/**
* 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.
* and prepares the signature request payload for the Near MPC Contract
*
* @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.
* @param txData - Minimal transaction data to be signed by Near MPC and executed on EVM
* @param nearGas - Manually specified gas to be sent with signature request
* @returns The transaction and request payload
*/
async getSignatureRequestPayload(
txData: BaseTx,
Expand All @@ -149,10 +158,11 @@ export class NearEthAdapter {
}

/**
* 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
* Builds a Near Transaction Payload for Signing serialized EVM Transaction
*
* @param transaction - RLP encoded (i.e. serialized) Ethereum Transaction
* @param nearGas - Optional gas parameter
* @returns Prepared Near Transaction with signerId as this.address
*/
async mpcSignRequest(
transaction: Hex,
Expand All @@ -170,11 +180,10 @@ export class NearEthAdapter {

/**
* Builds a complete, unsigned transaction (with nonce, gas estimates, current prices)
* and payload bytes in preparation to be relayed to Near MPC contract.
* 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).
* @param tx - Minimal transaction data to be signed by Near MPC and executed on EVM
* @returns Transaction and its bytes (the payload to be signed on Near)
*/
async createTxPayload(tx: BaseTx): Promise<TxPayload> {
const transaction = await this.buildTransaction(tx);
Expand All @@ -187,32 +196,44 @@ export class NearEthAdapter {
}

/**
* 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.
* Transforms minimal transaction request data into a fully populated EVM transaction
*
* @param tx - Minimal transaction request data
* @returns Serialized (aka RLP encoded) transaction
*/
async buildTransaction(tx: BaseTx): Promise<Hex> {
const transaction = await populateTx(tx, this.address);
return serializeTransaction(transaction);
}

// Below code is inspired by https://github.com/Connor-ETHSeoul/near-viem

/**
* Signs typed data according to EIP-712
*
* @param typedData - The typed data to sign
* @returns The signature hash
*/
async signTypedData<
const typedData extends TypedData | Record<string, unknown>,
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData,
>(typedData: TypedDataDefinition<typedData, primaryType>): Promise<Hash> {
return this.sign(hashTypedData(typedData));
}

/**
* Signs a message according to personal_sign
*
* @param message - The message to sign
* @returns The signature hash
*/
async signMessage(message: SignableMessage): Promise<Hash> {
return this.sign(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).
* 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: `0x${string}` | Uint8Array): Promise<Hex> {
const signature = await this.mpcContract.requestSignature({
Expand All @@ -224,14 +245,10 @@ export class NearEthAdapter {
}

/**
* Encodes a signature request for submission to the Near-Ethereum transaction MPC contract.
* 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.
* @param signRequest - The signature request data containing method, chain ID, and parameters
* @returns The encoded Near-Ethereum transaction data, original EVM message, and recovery data
*/
async encodeSignRequest(
signRequest: SignRequestData
Expand Down
2 changes: 2 additions & 0 deletions src/chains/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./ethereum";
export * from "./near";
57 changes: 29 additions & 28 deletions src/chains/near.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
import { keyStores, KeyPair, connect, Account } from "near-api-js";
import { NearConfig } from "near-api-js/lib/near";
import { NearAccountConfig } from "../types/interfaces";

/** Gas unit constant for NEAR transactions (1 TeraGas) */
export const TGAS = 1000000000000n;

/** Default deposit value for NEAR transactions */
export const NO_DEPOSIT = "0";

/** Valid NEAR network identifiers */
type NetworkId = "mainnet" | "testnet";

/**
* Extracts the network ID from a given NEAR account ID.
* If the account ID does not end with "near" or "testnet", it logs a warning.
* Defaults to "mainnet" if the network ID is not "testnet".
* Extracts the network ID from a given NEAR account ID
*
* @param accountId - The NEAR account ID to extract the network ID from.
* @returns The network ID, either "mainnet" or "testnet".
* @param accountId - The NEAR account ID to analyze
* @returns The network ID ("mainnet" or "testnet")
* @remarks If the account ID doesn't end with "near" or "testnet", defaults to "mainnet"
*/
export function getNetworkId(accountId: string): NetworkId {
const accountExt = accountId.split(".").pop() || "";
Expand All @@ -21,10 +25,10 @@ export function getNetworkId(accountId: string): NetworkId {
}

/**
* Generates a NEAR configuration object based on the provided network ID.
* Generates a NEAR configuration object for a specific network
*
* @param networkId - The network ID, either "mainnet" or "testnet".
* @returns A NearConfig object containing the network ID and node URL.
* @param networkId - The target network identifier
* @returns Configuration object for NEAR connection
*/
export function configFromNetworkId(networkId: NetworkId): NearConfig {
return {
Expand All @@ -34,27 +38,24 @@ export function configFromNetworkId(networkId: NetworkId): NearConfig {
}

/**
* Loads Near Account from provided keyPair and accountId
* Creates a NEAR Account instance from provided credentials
*
* @param keyPair {KeyPair}
* @param accountId {string}
* @param network {NearConfig} network settings
* @returns A Promise that resolves to a NEAR Account instance.
* @param config - Configuration containing account ID, network, and key pair
* @returns A NEAR Account instance
*/
export const nearAccountFromKeyPair = async (config: {
keyPair: KeyPair;
accountId: string;
network: NearConfig;
}): Promise<Account> => {
export const nearAccountFromKeyPair = async (
config: NearAccountConfig
): Promise<Account> => {
return createNearAccount(config.accountId, config.network, config.keyPair);
};

/** Minimally sufficient Account instance to construct readonly MpcContract connection.
* Can't be used to change methods.
/**
* Creates a read-only NEAR Account instance from an account ID
*
* @param accountId {string}
* @param network {NearConfig} network settings
* @returns A Promise that resolves to a NEAR Account instance.
* @param accountId - The NEAR account identifier
* @param network - The NEAR network configuration
* @returns A read-only NEAR Account instance
* @remarks This account cannot perform write operations
*/
export const nearAccountFromAccountId = async (
accountId: string,
Expand All @@ -64,12 +65,12 @@ export const nearAccountFromAccountId = async (
};

/**
* Creates a NEAR account instance using the provided account ID, network configuration, and optional key pair.
* Creates a NEAR Account instance with optional write capabilities
*
* @param accountId - The NEAR account ID.
* @param network - The NEAR network configuration.
* @param keyPair - (Optional) The key pair for the account.
* @returns A Promise that resolves to a NEAR Account instance.
* @param accountId - The NEAR account identifier
* @param network - The NEAR network configuration
* @param keyPair - Optional key pair for write access
* @returns A NEAR Account instance
*/
export const createNearAccount = async (
accountId: string,
Expand Down
Loading