Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ jobs:
- name: Lint & Build
run: |
bun lint
bun run test
bun test
bun run build
188 changes: 159 additions & 29 deletions bun.lock

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,8 @@
"prettier": "^3.6.2",
"ts-jest": "^29.4.1",
"typescript": "^5.9.2"
},
"dependencies": {
"@bitte/core": "."
}
}
1 change: 1 addition & 0 deletions packages/agent-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
},
"dependencies": {
"@bitte-ai/types": "^0.8.1",
"near-api-js": "^6.3.0",
"viem": "^2.37.5",
"zerion-sdk": "^0.1.6"
}
Expand Down
1 change: 1 addition & 0 deletions packages/agent-sdk/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export * from "./evm";
export * from "./request";
export * from "./error";
export * from "./misc";
export * from "./near";
export * from "./openai";
19 changes: 19 additions & 0 deletions packages/agent-sdk/src/near/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export declare const DEFAULT_GAS = "200000000000000";
export declare const MAX_GAS = "300000000000000";
export declare const ONE_YOCTO = "1";
export declare const TOKEN_CONTRACT_SPEC = "nft-1.0.0";
export declare const DEPLOY_CONTRACT_V1_DEPOSIT: string;
export declare const DEPLOY_CONTRACT_V2_DEPOSIT: string;
export declare const LISTING_DEPOSIT: string;
export declare const FT_STORAGE_DEPOSIT: string;
export const GAS_CONSTANTS = {
DEFAULT_GAS: "200000000000000",
OPTIMAL_GAS: "225000000000000",
MAX_GAS: "300000000000000",
FT_TRANSFER: "15000000000000",
};
export declare const STORAGE_PRICE_PER_BYTE_EXPONENT = 19;
export declare const DEPOSIT_FOR_BURN = "1";
export declare const GAS_FOR_BURN = "200000000000000";
export declare const DEPOSIT_FOR_TRANSFER = "1";
export declare const GAS_FOR_TRANSFER = "200000000000000";
3 changes: 3 additions & 0 deletions packages/agent-sdk/src/near/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./constants";
export * from "./price";
export * from "./rpc";
45 changes: 45 additions & 0 deletions packages/agent-sdk/src/near/price.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const BINANCE_API =
"https://api.binance.com/api/v3/ticker/price?symbol=NEARUSDT";
const COIN_GECKO_API =
"https://api.coingecko.com/api/v3/simple/price?ids=near&vs_currencies=usd";

export async function getNearPriceUSD(): Promise<number> {
const errs: string[] = [];

try {
const price = await coinGeckoPrice();
return price;
} catch (err) {
errs.push(`coingecko: ${err}`);
}
try {
const price = await binancePrice();
return price;
} catch (err) {
errs.push(`binance: ${err}`);
}
throw new Error(`All price providers failed:\n- ${errs.join("\n- ")}`);
}

export async function binancePrice(): Promise<number> {
return fetchPrice<{ price: number }>(BINANCE_API, (x) => x.price);
}

export async function coinGeckoPrice(): Promise<number> {
return fetchPrice<{ near: { usd: number } }>(
COIN_GECKO_API,
(x) => x.near.usd,
);
}
// TODO: find out the token ID here and implement this.
// const LLAMA_FI_API = 'https://coins.llama.fi/prices/current/near-protocol';

async function fetchPrice<T>(
url: string,
tokenPrice: (data: T) => number,
): Promise<number> {
const res = await fetch(url);
if (!res.ok) throw new Error(`Failed to fetch NEAR price: ${res.statusText}`);
const data = (await res.json()) as T;
return tokenPrice(data);
}
45 changes: 45 additions & 0 deletions packages/agent-sdk/src/near/rpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Account, providers } from "near-api-js";

export interface RpcParams {
rpcUrl?: string;
}

export interface AccountParams extends RpcParams {
accountId: string;
}
export interface FTParams extends AccountParams {
contractId: string;
}

export async function getBalance({
accountId,
rpcUrl,
}: AccountParams): Promise<bigint> {
const provider = new providers.JsonRpcProvider({
url: rpcUrl || "https://rpc.mainnet.near.org",
});
const account = new Account(accountId, provider);
const { balance } = await account.getState();
return balance.available;
}

export async function ftBalance({
contractId,
accountId,
rpcUrl,
}: FTParams): Promise<string> {
const provider = new providers.JsonRpcProvider({
url: rpcUrl || "https://rpc.mainnet.near.org",
});
const result = await provider.callFunction<string>(
contractId,
"ft_balance_of",
{ account_id: accountId },
);
if (!result) {
throw new Error(
`Could not read ftBalance of ${accountId} for ${contractId}`,
);
}
return result;
}
14 changes: 14 additions & 0 deletions packages/agent-sdk/tests/near/near.price.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { binancePrice, coinGeckoPrice, getNearPriceUSD } from "../../src/near";

describe("near utilities", () => {
it.only("getNearPriceUSD", async () => {
expect(await getNearPriceUSD()).toBeDefined();
});

it("binancePrice", async () => {
expect(await binancePrice()).toBeDefined();
});
it("coinGeckoPrice", async () => {
expect(await coinGeckoPrice()).toBeDefined();
});
});
32 changes: 32 additions & 0 deletions packages/agent-sdk/tests/near/near.rpc.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { getBalance, ftBalance } from "../../src/near";

describe("near utilities", () => {
it("getBalance success", async () => {
expect(await getBalance({ accountId: "max-normal.near" })).toBeDefined();
});

it("getBalance fail", async () => {
await expect(() => getBalance({ accountId: "zebra" })).toThrow();
});

it("ftBalance success", async () => {
expect(
await ftBalance({
accountId: "max-normal.near",
contractId: "wrap.near",
}),
).toBeDefined();
});

it("ftBalance zero", async () => {
expect(
await ftBalance({ accountId: "zebra", contractId: "wrap.near" }),
).toBe("0");
});

it("ftBalance fail", async () => {
await expect(() =>
ftBalance({ accountId: "wrap.near", contractId: "zebra" }),
).toThrow();
});
});
2 changes: 1 addition & 1 deletion packages/agent-sdk/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "ES2020",
"target": "ES2022",
"moduleDetection": "force",

// Bundler mode
Expand Down