Skip to content

Commit

Permalink
Chain Agnostic Adapter (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
bh2smith authored Apr 25, 2024
1 parent 888371e commit 614d407
Show file tree
Hide file tree
Showing 18 changed files with 212 additions and 135 deletions.
4 changes: 0 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
NEAR_ACCOUNT_ID=
NEAR_ACCOUNT_PRIVATE_KEY=
NEAR_MULTICHAIN_CONTRACT=multichain-testnet-2.testnet

NODE_URL=https://rpc.sepolia.org
SCAN_URL=https://sepolia.etherscan.io
GAS_STATION_URL=https://sepolia.beaconcha.in/api/v1/execution/gasnow
53 changes: 23 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**DISCLAIMER: This should only be used for educational purposes.**

NEAR-CA is a TypeScript library that provides an abstraction layer for interacting with the NEAR blockchain. It simplifies the process of performing transactions and managing accounts on NEAR and Ethereum chains.
NEAR-CA is a TypeScript library that provides an abstraction layer for interacting with the NEAR blockchain. It simplifies the process of performing transactions and managing accounts on NEAR and Ethereum chains.

Intended to be used on server-side applications only.

Expand Down Expand Up @@ -41,48 +41,44 @@ For Ethereum, you can derive addresses, create payloads for transactions, and se

```typescript
import dotenv from "dotenv";
import { MultichainContract, NearEthAdapter, nearAccountFromEnv } from "near-ca";
import {
MultichainContract,
NearEthAdapter,
nearAccountFromEnv,
} from "near-ca";

dotenv.config();
// Could also import and use nearAccountFromKeyPair here ;)
const account = await nearAccountFromEnv();
// Near Config
const near = {
mpcContract: new MultichainContract(
account,
process.env.NEAR_MULTICHAIN_CONTRACT!
),
derivationPath: "ethereum,1",
};

// EVM Config
const evm = {
providerUrl: process.env.NODE_URL!,
scanUrl: process.env.SCAN_URL!,
gasStationUrl: process.env.GAS_STATION_URL!,
};

const neareth = await NearEthAdapter.fromConfig({ near, evm });

await neareth.signAndSendTransaction({
receiver: "0xdeADBeeF0000000000000000000000000b00B1e5",
amount: 0.00000001,
// Optional Set nearGas (default is 200 TGAS - which still sometimes doesn't work!)

const adapter = await NearEthAdapter.fromConfig({
mpcContract: new MultichainContract(
account,
process.env.NEAR_MULTICHAIN_CONTRACT!
),
derivationPath: "ethereum,1",
});

await adapter.signAndSendTransaction({
receiver: "0xdeADBeeF0000000000000000000000000b00B1e5",
amount: 0.00000001,
chainId: 11_155_111,
// Optional Set nearGas (default is 200 TGAS - which still sometimes doesn't work!)
});
```

### Other Examples

Each of the following scripts can be run with
Each of the following scripts can be run with

```bash
npx ts-node examples/*.ts
```

1. [(Basic) Send ETH](./examples/send-eth.ts)
2. **WETH**
- [Deposit (aka wrap-ETH)](./examples/weth/wrap.ts)
- [Withdraw (aka unwrap-ETH)](./examples/weth/wrap.ts)
- [Deposit (aka wrap-ETH)](./examples/weth/wrap.ts)
- [Withdraw (aka unwrap-ETH)](./examples/weth/wrap.ts)
3. [Transfer ERC721](./examples/nft/erc721/transfer.ts)
4. [(Advanced) Buy NFT On Opensea](./examples/opensea.ts)

Expand All @@ -93,8 +89,5 @@ Before using NEAR-CA, ensure you have the following environment variables set:
- `NEAR_ACCOUNT_ID`: Your NEAR account identifier.
- `NEAR_ACCOUNT_PRIVATE_KEY`: Your NEAR account private key.
- `NEAR_MULTICHAIN_CONTRACT`: The NEAR contract that handles multichain operations.
- `NODE_URL=https://rpc.sepolia.org`
- `SCAN_URL=https://sepolia.etherscan.io`
- `GAS_STATION_URL=https://sepolia.beaconcha.in/api/v1/execution/gasnow`

Copy the `.env.example` file and place these values in `.env`
5 changes: 3 additions & 2 deletions examples/nft/erc1155/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import erc1155Abi from "../../abis/ERC1155.json";
import { setupNearEthAdapter } from "../../setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter } from "../../setup";
import { encodeFunctionData } from "viem";

const run = async (): Promise<void> => {
Expand All @@ -12,12 +12,13 @@ const run = async (): Promise<void> => {
const callData = encodeFunctionData({
abi: erc1155Abi,
functionName: "safeTransferFrom(address,address,uint256,uint256,bytes)",
args: [evm.ethPublicKey(), to, tokenId, 1, "0x"],
args: [evm.address, to, tokenId, 1, "0x"],
});

await evm.signAndSendTransaction({
to: tokenAddress,
data: callData,
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
3 changes: 2 additions & 1 deletion examples/nft/erc721/mint.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { encodeFunctionData } from "viem";
import { setupNearEthAdapter } from "../../setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter } from "../../setup";

const run = async (): Promise<void> => {
const adapter = await setupNearEthAdapter();
Expand All @@ -11,6 +11,7 @@ const run = async (): Promise<void> => {
functionName: "safeMint",
args: ["0xAA5FcF171dDf9FE59c985A28747e650C2e9069cA"],
}),
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
5 changes: 3 additions & 2 deletions examples/nft/erc721/transfer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import erc721ABI from "../../abis/ERC721.json";
import { encodeFunctionData } from "viem";
import { setupNearEthAdapter } from "../../setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter } from "../../setup";

const run = async (): Promise<void> => {
const neareth = await setupNearEthAdapter();
Expand All @@ -14,8 +14,9 @@ const run = async (): Promise<void> => {
data: encodeFunctionData({
abi: erc721ABI,
functionName: "safeTransferFrom(address,address,uint256)",
args: [neareth.ethPublicKey(), to, tokenId],
args: [neareth.address, to, tokenId],
}),
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
3 changes: 2 additions & 1 deletion examples/nft/setApprovalForAll.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import erc721ABI from "../abis/ERC721.json";
import { encodeFunctionData } from "viem";
import { setupNearEthAdapter } from "../setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter } from "../setup";

const run = async (): Promise<void> => {
const neareth = await setupNearEthAdapter();
Expand All @@ -14,6 +14,7 @@ const run = async (): Promise<void> => {
functionName: "setApprovalForAll",
args: [operator, true],
}),
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
5 changes: 3 additions & 2 deletions examples/opensea.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { OpenSeaSDK, Chain, OrderSide } from "opensea-js";
import { setupNearEthAdapter, sleep } from "./setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter, sleep } from "./setup";
import * as readline from "readline";
import { ethers } from "ethers";
import { Address, Hex, encodeFunctionData } from "viem";
Expand Down Expand Up @@ -39,7 +39,7 @@ const run = async (slug: string): Promise<void> => {
// This sleep is due to free-tier testnet rate limiting.
await sleep(1000);
const data = await openseaSDK.api.generateFulfillmentData(
evm.ethPublicKey(),
evm.address,
cheapestAvailable.order_hash,
cheapestAvailable.protocol_address,
OrderSide.ASK
Expand Down Expand Up @@ -74,6 +74,7 @@ const run = async (slug: string): Promise<void> => {
to: tx.to as Address,
value: BigInt(tx.value),
data: callData as Hex,
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
3 changes: 2 additions & 1 deletion examples/send-eth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import dotenv from "dotenv";
import { setupNearEthAdapter } from "./setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter } from "./setup";
dotenv.config();

const run = async (): Promise<void> => {
Expand All @@ -8,6 +8,7 @@ const run = async (): Promise<void> => {
to: "0xdeADBeeF0000000000000000000000000b00B1e5",
// THIS IS ONE WEI!
value: 1n,
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
19 changes: 7 additions & 12 deletions examples/setup.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
import dotenv from "dotenv";
import { MultichainContract, NearEthAdapter, nearAccountFromEnv } from "../src";

export const SEPOLIA_CHAIN_ID = 11_155_111;

export async function setupNearEthAdapter(): Promise<NearEthAdapter> {
dotenv.config();
const account = await nearAccountFromEnv();
return NearEthAdapter.fromConfig({
evm: {
providerUrl: process.env.NODE_URL!,
scanUrl: process.env.SCAN_URL!,
gasStationUrl: process.env.GAS_STATION_URL!,
},
near: {
mpcContract: new MultichainContract(
account,
process.env.NEAR_MULTICHAIN_CONTRACT!
),
derivationPath: "ethereum,1",
},
mpcContract: new MultichainContract(
account,
process.env.NEAR_MULTICHAIN_CONTRACT!
),
derivationPath: "ethereum,1",
});
}

Expand Down
2 changes: 1 addition & 1 deletion examples/sign-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ dotenv.config();
const run = async (): Promise<void> => {
const evm = await setupNearEthAdapter();
const message = "Hello World";
console.log(`Signing "${message}" with ${evm.ethPublicKey()}`);
console.log(`Signing "${message}" with ${evm.address}`);

const signature = await evm.signMessage(message);
console.log("Got Validated Signature", signature);
Expand Down
3 changes: 2 additions & 1 deletion examples/weth/unwrap.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import wethABI from "../abis/WETH.json";
import { encodeFunctionData, parseEther } from "viem";
import { setupNearEthAdapter } from "../setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter } from "../setup";

const run = async (): Promise<void> => {
const neareth = await setupNearEthAdapter();
Expand All @@ -15,6 +15,7 @@ const run = async (): Promise<void> => {
functionName: "withdraw",
args: [parseEther(withdrawAmount.toString())],
}),
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
3 changes: 2 additions & 1 deletion examples/weth/wrap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { parseEther } from "viem";
import { setupNearEthAdapter } from "../setup";
import { SEPOLIA_CHAIN_ID, setupNearEthAdapter } from "../setup";

const run = async (): Promise<void> => {
const neareth = await setupNearEthAdapter();
Expand All @@ -11,6 +11,7 @@ const run = async (): Promise<void> => {
to: sepoliaWETH,
value: ethAmount,
data: deposit,
chainId: SEPOLIA_CHAIN_ID,
});
};

Expand Down
Loading

0 comments on commit 614d407

Please sign in to comment.