diff --git a/bun.lockb b/bun.lockb index 8eb3799c..d0f4f2ed 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index aa337f10..3a118d46 100644 --- a/package.json +++ b/package.json @@ -1,63 +1,64 @@ { - "name": "@effectai/effect-js", - "version": "2.0.0", - "description": "Effect Network Javscript/Typescript SDK (for [https://effect.network](https://effect.network))", - "main": "./dist/exports/index.js", - "module": "./dist/exports/index.js", - "browser": "dist/exports/index.js", - "types": "./dist/exports/index.d.ts", - "files": ["dist"], - "scripts": { - "test": "bun --env-file=.env test", - "test:watch": "bun --env-file=.env test --watch", - "test:coverage": "bun --env-file=.env test --coverage", - "test:mainnet": "bun --env-file=.env.mainnet test", - "dev": "tsc -w", - "build": "tsc --module es2020", - "lint": "bun biome lint --apply .", - "format": "biome format --write .", - "check": "bun biome check --apply .", - "changeset": "changeset", - "changeset:public": "bun scripts/updateVersion.ts && bun build && changeset publish", - "changeset:version": "changeset version && bun install --frozen-lockfile && bun scripts/updateVersion.ts", - "docs:dev": "cd docs && bun run dev", - "docs:build": "cd docs && bun run build", - "docs:preview": "cd docs && bun run preview" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/effectai/effect-js.git" - }, - "keywords": ["efx", "AI", "blockchain", "microtasks"], - "author": { - "name": "Effect-AI", - "url": "https://effect.network", - "email": "hello@effect.ai" - }, - "publishConfig": { - "access": "public" - }, - "license": "MIT", - "bugs": { - "url": "https://github.com/effectai/effect-js/issues" - }, - "homepage": "https://github.com/effectai/effect-js#readme", - "devDependencies": { - "@biomejs/biome": "1.7.0", - "@changesets/changelog-github": "^0.4.5", - "@changesets/cli": "^2.23.2", - "@size-limit/preset-big-lib": "^11.1.2", - "@greymass/abi2core": "^2.0.1", - "typescript": "^5.4.3" - }, - "dependencies": { - "@wharfkit/antelope": "^1.0.7", - "@wharfkit/session": "^1.2.8", - "@wharfkit/wallet-plugin-privatekey": "^1.0.0", - "ajv": "^8.12.0", - "atomicassets": "^1.5.1", - "idb-keyval": "^6.2.1", - "node-localstorage": "^3.0.5" - }, - "trustedDependencies": ["@biomejs/biome"] + "name": "@effectai/effect-js", + "version": "2.0.0", + "description": "Effect Network Javscript/Typescript SDK (for [https://effect.network](https://effect.network))", + "main": "./dist/exports/index.js", + "module": "./dist/exports/index.js", + "browser": "dist/exports/index.js", + "types": "./dist/exports/index.d.ts", + "files": ["dist"], + "scripts": { + "test": "bun --env-file=.env test", + "test:watch": "bun --env-file=.env test --watch", + "test:coverage": "bun --env-file=.env test --coverage", + "test:mainnet": "bun --env-file=.env.mainnet test", + "dev": "tsc -w", + "build": "tsc --module es2020", + "lint": "bun biome lint --apply .", + "format": "biome format --write .", + "check": "bun biome check --apply .", + "changeset": "changeset", + "changeset:public": "bun scripts/updateVersion.ts && bun build && changeset publish", + "changeset:version": "changeset version && bun install --frozen-lockfile && bun scripts/updateVersion.ts", + "docs:dev": "cd docs && bun run dev", + "docs:build": "cd docs && bun run build", + "docs:preview": "cd docs && bun run preview" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/effectai/effect-js.git" + }, + "keywords": ["efx", "AI", "blockchain", "microtasks"], + "author": { + "name": "Effect-AI", + "url": "https://effect.network", + "email": "hello@effect.ai" + }, + "publishConfig": { + "access": "public" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/effectai/effect-js/issues" + }, + "homepage": "https://github.com/effectai/effect-js#readme", + "devDependencies": { + "@biomejs/biome": "1.7.0", + "@changesets/changelog-github": "^0.4.5", + "@changesets/cli": "^2.23.2", + "@greymass/abi2core": "^2.0.1", + "@size-limit/preset-big-lib": "^11.1.2", + "@types/bun": "^1.1.1", + "typescript": "^5.4.3" + }, + "dependencies": { + "@wharfkit/antelope": "^1.0.7", + "@wharfkit/session": "^1.2.8", + "@wharfkit/wallet-plugin-privatekey": "^1.0.0", + "ajv": "^8.12.0", + "atomicassets": "^1.5.1", + "idb-keyval": "^6.2.1", + "node-localstorage": "^3.0.5" + }, + "trustedDependencies": ["@biomejs/biome"] } diff --git a/src/actions/tasks/batch/createBatch.ts b/src/actions/tasks/batch/createBatch.ts index c4e9adc5..3bc39712 100644 --- a/src/actions/tasks/batch/createBatch.ts +++ b/src/actions/tasks/batch/createBatch.ts @@ -81,26 +81,34 @@ export const publishBatchAction = ({ export type CreateBatchArgs = { client: Client; - batch: Omit; - data: Record; + campaignId: number; + repetitions: number; + reward: number; + taskData: Record; }; -export const createBatch = async ({ client, batch, data }: CreateBatchArgs) => { +export const createBatch = async ({ + client, + campaignId, + repetitions, + reward, + taskData, +}: CreateBatchArgs) => { try { if (!client.session) { throw new SessionNotFoundError("Session is required for this method."); } const forceSettings = await getForceSettings({ client }); - const { transact, vAccount } = client.session; + const { transact, vAccount, actor } = client.session; if (!vAccount) { - throw new Error("No vAccountId found"); + throw new Error("vAccount not found"); } - const campaign = await getCampaignById({ client, id: batch.campaign_id }); - const assetQuantity = Asset.from(campaign.reward.quantity); - const batchPrice = assetQuantity.value * batch.repetitions; + const campaign = await getCampaignById({ client, id: campaignId }); + const assetQuantity = Asset.from(reward, " EFX"); + const batchPrice = assetQuantity.value * repetitions; // Check if the user has enough funds to pay for the batch // if (Asset.from(vacc.balance.quantity).value < batchPrice) { @@ -114,12 +122,18 @@ export const createBatch = async ({ client, batch, data }: CreateBatchArgs) => { // } const newBatchId = campaign.num_batches + 1; - const hash = await uploadIpfsResource({ client, data }); + const hash = await uploadIpfsResource({ client, data: taskData }); const makeBatch = createBatchAction({ client, forceSettings, - batch, + batch: { + id: newBatchId, + payer: actor.toString(), + campaign_id: campaignId, + repetitions, + content: { field_0: 0, field_1: hash }, + }, hash, }); @@ -133,7 +147,7 @@ export const createBatch = async ({ client, batch, data }: CreateBatchArgs) => { const publishBatch = publishBatchAction({ client, batchId: newBatchId, - numTasks: batch.repetitions, + numTasks: repetitions, }); // TODO Check if batchId is correct. diff --git a/src/actions/tasks/campaigns/createCampaign.ts b/src/actions/tasks/campaigns/createCampaign.ts index eaecba56..950f453c 100644 --- a/src/actions/tasks/campaigns/createCampaign.ts +++ b/src/actions/tasks/campaigns/createCampaign.ts @@ -1,56 +1,81 @@ -import type { - Content, - Mkcampaign, -} from "../../../@generated/types/effecttasks2"; +import type { AnyAction } from "@wharfkit/antelope"; import type { Client } from "../../../client"; import { SessionNotFoundError } from "../../../errors"; import { useEFXContracts } from "../../../utils/state"; import { uploadIpfsResource } from "../../ipfs/uploadIpfsResource"; import type { CampaignInfo } from "./getCampaigns"; +import type { Mkcampaign, Quali } from "../../../@generated/types/effecttasks2"; + +export type CreateCampaignActionArgs = { + client: Client; + campaign: Mkcampaign; +}; + +export const createCampaignAction = ({ + client, + campaign, +}: CreateCampaignActionArgs): AnyAction => { + if (!client.session) { + throw new SessionNotFoundError("Session is required for this method."); + } + + const { actor } = client.session; + const { tasks } = useEFXContracts(client); + + return { + account: tasks, + name: "mkcampaign", + authorization: [ + { + actor, + permission: "active", + }, + ], + data: campaign, + }; +}; export type CreateCampaignArgs = { client: Client; - campaign: Omit; - data: CampaignInfo; + campaign: CampaignInfo; + reward: number; + maxTaskTime: number; + qualitications?: Quali[]; }; export const createCampaign = async ({ client, campaign, - data, + reward, + maxTaskTime, + qualitications, }: CreateCampaignArgs) => { - if (!data) { - throw new Error("Data is required for this method."); - } - if (!client.session) { throw new SessionNotFoundError("Session is required for this method."); } - const { transact, actor, authorization } = client.session; - const { tasks, token } = useEFXContracts(client); + const { transact } = client.session; + const { token } = useEFXContracts(client); try { // Upload Campaign data to IPFS - const hash = await uploadIpfsResource({ client, data }); + const hash = await uploadIpfsResource({ client, data: campaign }); const response = await transact({ - action: { - account: tasks, - name: "mkcampaign", - authorization, - data: { - owner: actor, - content: { field_0: 0, field_1: hash }, - max_task_time: campaign.max_task_time, + action: createCampaignAction({ + client, + campaign: { + max_task_time: maxTaskTime, reward: { - quantity: campaign.reward.quantity, + quantity: `${reward.toFixed(4)} EFX`, // `1.0000 EFX` contract: token, }, - qualis: campaign.qualis ?? [], - payer: actor, + payer: client.session.actor.toString(), + content: { field_0: maxTaskTime, field_1: hash }, + qualis: qualitications ?? [], + owner: ["name", client.session.actor.toString()], }, - }, + }), }); return response; diff --git a/src/actions/token/getBalance.test.ts b/src/actions/token/getBalance.test.ts new file mode 100644 index 00000000..485757f4 --- /dev/null +++ b/src/actions/token/getBalance.test.ts @@ -0,0 +1,25 @@ +import { describe, test, expect } from "bun:test"; +import { getPrice } from "./getPrice"; +import { getBalance } from "./getBalance"; +import { swap, type SwapArgs } from "./swap"; +import { createClient } from "../../client"; +import { testClientSession } from "../../testHelper"; +import { eos, jungle4 } from "../../exports"; +import { Name } from "@wharfkit/antelope"; + +describe("getBalance", async () => { + test("getBalance() should retrieve balance from user on mainnet", async () => { + const client = createClient({ network: jungle4 }); + const actor = Name.from("forcedev1234"); + const balance = await getBalance({ client, actor }); + expect(balance).toBeDefined(); + expect(balance.toString()).toBeDefined(); + expect(balance.toString()).toContain("EFX"); + }); + + test("getBalance() should throw Error retrieving balance from unknown user.", async () => { + const client = createClient({ network: eos }); + const actor = Name.from("cryptonode99"); + expect(async () => await getBalance({ client, actor })).toThrowError(); + }); +}); diff --git a/src/actions/token/getDefiBoxPair.test.ts b/src/actions/token/getDefiBoxPair.test.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/actions/token/getPrice.test.ts b/src/actions/token/getPrice.test.ts new file mode 100644 index 00000000..b307a95c --- /dev/null +++ b/src/actions/token/getPrice.test.ts @@ -0,0 +1,8 @@ +describe("getPrice", async () => { + test("getPrice() should retrieve price on mainnet", async () => { + const client = createClient({ network: eos }); + const price = await getPrice(); + expect(price).toBeDefined(); + expect(price).toBeNumber(); + }); +}); diff --git a/src/actions/token/swap.test.ts b/src/actions/token/swap.test.ts new file mode 100644 index 00000000..0d2fac57 --- /dev/null +++ b/src/actions/token/swap.test.ts @@ -0,0 +1,29 @@ +describe("buildSwapAction", async () => { + test.todo("buildSwapAction() should return a swap action object."); +}); + +describe("Swap", async () => { + // Use Mainnet + + test("swap() should throw an error when Session is not set on Client.", async () => { + const swapArgs: SwapArgs = { + client: createClient({ network: jungle4 }), + amount: 1, + direction: "UsdtToEfx", + }; + + expect(async () => await swap(swapArgs)).toThrow( + new Error("Error swapping: Error: Session is required for this method."), + ); + }); + + test("swap() should fail when amount is 0", async () => { + const swapArgs: SwapArgs = { + client: await testClientSession({ testEnvNetwork: jungle4 }), + amount: 0, + direction: "UsdtToEfx", + }; + + expect(async () => await swap(swapArgs)).toThrow(); + }); +}); diff --git a/src/actions/vaccount/createAccount.test.ts b/src/actions/vaccount/createAccount.test.ts index ab956b37..3ef79d4b 100644 --- a/src/actions/vaccount/createAccount.test.ts +++ b/src/actions/vaccount/createAccount.test.ts @@ -1,9 +1,12 @@ +import { Name } from "@wharfkit/antelope"; + import { expect, test, describe, mock } from "bun:test"; -import { destructureEnv, testClientSession } from "../../testHelper"; + import { createClient } from "../../client"; import { createVAccount } from "./createAccount"; -import { Name } from "@wharfkit/antelope"; + import { jungle4 } from "../../exports"; +import { destructureEnv, testClientSession } from "../../../test/src/utils.js"; describe("Create Virtual account", () => { const testEnvNetwork = jungle4; diff --git a/src/actions/vaccount/deposit.test.ts b/src/actions/vaccount/deposit.test.ts index 42c380de..6dbc9ae5 100644 --- a/src/actions/vaccount/deposit.test.ts +++ b/src/actions/vaccount/deposit.test.ts @@ -1,9 +1,9 @@ import { describe, test, expect } from "bun:test"; import { deposit } from "./deposit"; -import { destructureEnv, testClientSession } from "../../testHelper"; import { eos, jungle4 } from "../../exports"; import { getOrCreateVAccount } from "./getOrCreate"; import { Name } from "@wharfkit/antelope"; +import { testClientSession, destructureEnv } from "../../../test/src/utils"; describe("deposit", async () => { test.todo("Should throw an error when Session is not set on Client.", () => { diff --git a/src/actions/vaccount/getAccounts.test.ts b/src/actions/vaccount/getAccounts.test.ts index 7c3505ec..75fa2eef 100644 --- a/src/actions/vaccount/getAccounts.test.ts +++ b/src/actions/vaccount/getAccounts.test.ts @@ -1,7 +1,8 @@ import { expect, test, describe, beforeAll } from "bun:test"; import type { VAccount } from "../../types/user"; -import { testClientSession } from "../../testHelper"; import type { Client } from "../../client"; +import { testClientSession } from "../../../test/src/utils"; + import { getVAccounts, getAccountById } from "./getAccounts"; import { Name } from "@wharfkit/antelope"; import { jungle4 } from "../../exports"; diff --git a/src/testHelper.ts b/test/src/utils.ts similarity index 90% rename from src/testHelper.ts rename to test/src/utils.ts index 6ae93aff..ef0d22f8 100644 --- a/src/testHelper.ts +++ b/test/src/utils.ts @@ -5,10 +5,10 @@ import { PermissionLevel, } from "@wharfkit/session"; import { WalletPluginPrivateKey } from "@wharfkit/wallet-plugin-privatekey"; -import { jungle4, eos } from "../src/exports"; -import { createClient } from "./../src/client"; -import type { Client } from "./../src/client"; -import type { Network } from "./types/network"; +import { jungle4, eos } from "../../src/exports"; +import { createClient } from "../../src/client"; +import type { Client } from "../../src/client"; +import type { Network } from "../../src/types/network"; declare module "bun" { interface Env { diff --git a/tsconfig.json b/tsconfig.json index 250d1a38..bc381561 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "rootDir": "./", "downlevelIteration": true, "esModuleInterop": true, "importHelpers": true, @@ -16,5 +17,5 @@ "skipLibCheck": true }, "exclude": ["node_modules/**/*", "**/*.test.ts"], - "include": ["src/**/*", "abis/**/*"] + "include": ["src/**/*", "abis/**/*", "test/testHelper.ts"] }