Skip to content

Commit

Permalink
Fix sender on EVM instance construction (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
bh2smith authored Mar 21, 2024
1 parent 632ee4d commit 550a8d5
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 29 deletions.
3 changes: 1 addition & 2 deletions examples/opensea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ const run = async (slug: string): Promise<void> => {
// This sleep is due to free-tier testnet rate limiting.
await sleep(1000);
const evm = await setupNearEthConnection();
const sender = await evm.getSender();
const data = await openseaSDK.api.generateFulfillmentData(
sender,
evm.sender,
cheapestAvailable.order_hash,
cheapestAvailable.protocol_address,
OrderSide.ASK
Expand Down
3 changes: 2 additions & 1 deletion examples/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ dotenv.config();
export async function setupNearEthConnection(): Promise<EVM> {
// This also reads from process.env!
const account = await getNearAccount();
return new EVM({
return EVM.fromConfig({
providerUrl: process.env.NODE_URL!,
scanUrl: process.env.SCAN_URL!,
gasStationUrl: process.env.GAS_STATION_URL!,
mpcContract: new MultichainContract(
account,
process.env.NEAR_MULTICHAIN_CONTRACT!
),
derivationPath: "ethereum,1",
});
}
3 changes: 1 addition & 2 deletions examples/transfer-1155.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ const run = async (): Promise<void> => {
const tokenAddress = "0x284c37b0fcb72034ff25855da57fcf097b255474";
const tokenId = 1;
const to = "0x8d99F8b2710e6A3B94d9bf465A98E5273069aCBd";
const from = await evm.getSender();

const callData = encodeFunctionData({
abi: erc1155Abi,
functionName: "safeTransferFrom(address,address,uint256,uint256,bytes)",
args: [from, to, tokenId, 1, "0x"],
args: [evm.sender, to, tokenId, 1, "0x"],
});

await evm.signAndSendTransaction({
Expand Down
3 changes: 1 addition & 2 deletions examples/transfer-nft.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { setupNearEthConnection } from "./setup";

const run = async (): Promise<void> => {
const evm = await setupNearEthConnection();
const sender = await evm.getSender();
const amount = 0;
// TODO retrieve from user:
const tokenAddress = "0xb5EF4EbB25fCA7603C028610ddc9233d399dA34d";
Expand All @@ -14,7 +13,7 @@ const run = async (): Promise<void> => {
const callData = encodeFunctionData({
abi: erc721ABI,
functionName: "safeTransferFrom(address,address,uint256)",
args: [sender, to, tokenId],
args: [evm.sender, to, tokenId],
});

await evm.signAndSendTransaction({
Expand Down
55 changes: 33 additions & 22 deletions src/chains/ethereum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export class EVM {
private scanUrl: string;
private gasStationUrl: string;
private mpcContract: MultichainContract;
private derivationPath: string;
sender: Address;

/**
* Constructs an EVM instance with the provided configuration.
Expand All @@ -38,40 +40,48 @@ export class EVM {
scanUrl: string;
gasStationUrl: string;
mpcContract: MultichainContract;
derivationPath: string;
sender: Address;
}) {
this.client = createPublicClient({ transport: http(config.providerUrl) });
this.scanUrl = config.scanUrl;
this.mpcContract = config.mpcContract;
this.gasStationUrl = config.gasStationUrl;
this.derivationPath = config.derivationPath;
this.sender = config.sender;
}

getSender(derivationPath?: string): Promise<Address> {
static async fromConfig(config: {
providerUrl: string;
scanUrl: string;
gasStationUrl: string;
mpcContract: MultichainContract;
derivationPath?: string;
}): Promise<EVM> {
const { derivationPath, ...rest } = config;
// Sender is uniquely determined by the derivation path!
const path = derivationPath || "ethereum,1";
return this.mpcContract.deriveEthAddress(path);
return new EVM({
sender: await config.mpcContract.deriveEthAddress(path),
derivationPath: path,
...rest,
});
}

signAndSendTransaction = async (
txData: BaseTx,
options?: {
derivationPath: string;
}
): Promise<void> => {
// Sender is uniquely determined by the derivation path!
const path = options?.derivationPath || "ethereum,1";
const sender = await this.getSender(path);
console.log("Creating Payload for sender:", sender);
const { transaction, payload } = await this.createTxPayload(txData, sender);
signAndSendTransaction = async (txData: BaseTx): Promise<void> => {
console.log("Creating Payload for sender:", this.sender);
const { transaction, payload } = await this.createTxPayload(txData);
console.log("Requesting signature from Near...");
const { big_r, big_s } = await this.mpcContract.requestSignature(
payload,
path
this.derivationPath
);

const signedTx = EVM.reconstructSignature(
transaction,
big_r,
big_s,
sender
this.sender
);
console.log("Relaying signed tx to EVM...");
await this.relayTransaction(signedTx);
Expand All @@ -93,14 +103,15 @@ export class EVM {
}

private async buildTransaction(
tx: BaseTx,
sender: Address
tx: BaseTx
): Promise<FeeMarketEIP1559Transaction> {
const nonce = await this.client.getTransactionCount({ address: sender });
const nonce = await this.client.getTransactionCount({
address: this.sender,
});
const { maxFeePerGas, maxPriorityFeePerGas } = await this.queryGasPrice();
const transactionData = {
nonce,
account: sender,
account: this.sender,
to: tx.receiver,
value: parseEther(tx.amount.toString()),
data: tx.data || "0x",
Expand All @@ -117,8 +128,8 @@ export class EVM {
return FeeMarketEIP1559Transaction.fromTxData(transactionDataWithGasLimit);
}

async createTxPayload(tx: BaseTx, sender: Address): Promise<TxPayload> {
const transaction = await this.buildTransaction(tx, sender);
async createTxPayload(tx: BaseTx): Promise<TxPayload> {
const transaction = await this.buildTransaction(tx);
console.log("Built Transaction", JSON.stringify(transaction));
const payload = Array.from(
new Uint8Array(transaction.getHashedMessageToSign().slice().reverse())
Expand All @@ -130,7 +141,7 @@ export class EVM {
transaction: FeeMarketEIP1559Transaction,
big_r: string,
big_s: string,
sender: string
sender: Address
): FeeMarketEIP1559Transaction => {
const r = Buffer.from(big_r.substring(2), "hex");
const s = Buffer.from(big_s, "hex");
Expand Down

0 comments on commit 550a8d5

Please sign in to comment.