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

feat: add Sui blockchain support #173

Merged
merged 21 commits into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
086e913
feat: add Sui blockchain support
devin-ai-integration[bot] Jan 3, 2025
c3d6fc0
chore: regenerate pnpm-lock.yaml
devin-ai-integration[bot] Jan 3, 2025
17aa01b
chore: fix import organization in Sui wallet files
devin-ai-integration[bot] Jan 3, 2025
f67101b
chore: regenerate pnpm-lock.yaml to include @types/node
devin-ai-integration[bot] Jan 3, 2025
8324f49
chore: add tsup config for sui wallet package
devin-ai-integration[bot] Jan 3, 2025
ec3e670
chore: add tsconfig for sui wallet package
devin-ai-integration[bot] Jan 3, 2025
3ee89f9
chore: fix import organization and type safety in Sui wallet
devin-ai-integration[bot] Jan 4, 2025
1d9aad7
fix: update Sui transaction handling and type references
devin-ai-integration[bot] Jan 4, 2025
f6c4b63
chore: fix lint issues in Sui wallet implementation
devin-ai-integration[bot] Jan 4, 2025
b7d8bdd
feat: make Sui transaction generic, rename response type, remove expl…
devin-ai-integration[bot] Jan 4, 2025
7c04bea
fix: update Sui transaction handling to use transaction field
devin-ai-integration[bot] Jan 4, 2025
d273241
fix: update Sui transaction handling to follow PTB docs
devin-ai-integration[bot] Jan 4, 2025
fe7b3d3
chore: update @mysten/sui.js to v0.54.1 and revert premature Transact…
devin-ai-integration[bot] Jan 4, 2025
1e08bd6
fix: update Sui transaction handling to use TransactionBlock
devin-ai-integration[bot] Jan 4, 2025
49f546d
chore: regenerate pnpm-lock.yaml
devin-ai-integration[bot] Jan 4, 2025
aab8111
fix: update Sui SDK imports to use dist/cjs paths
devin-ai-integration[bot] Jan 4, 2025
e964f98
fix: update formatting to match Biome linting rules
devin-ai-integration[bot] Jan 4, 2025
0f228ef
docs: improve documentation and make transaction handling more generic
devin-ai-integration[bot] Jan 4, 2025
bc4ba32
style: remove extra whitespace in sendSui.plugin.ts
devin-ai-integration[bot] Jan 4, 2025
a21ca68
Fix PR
0xaguspunk Jan 4, 2025
36fd7a1
Add changeset
0xaguspunk Jan 4, 2025
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
4 changes: 4 additions & 0 deletions goat.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@
"name": "[Wallet] 🌞 solana",
"path": "./typescript/packages/wallets/solana"
},
{
"name": "[Wallet] 💧 sui",
"path": "./typescript/packages/wallets/sui"
},
{
"name": "[Wallet] 🪨 evm",
"path": "./typescript/packages/wallets/evm"
Expand Down
6 changes: 6 additions & 0 deletions typescript/.changeset/giant-balloons-confess.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@goat-sdk/wallet-sui": patch
"@goat-sdk/core": patch
---

Add Sui support
6 changes: 5 additions & 1 deletion typescript/packages/core/src/types/Chain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
* @param type - "evm" or "solana", extend this union as needed (e.g., "sui")
* @param id - Chain ID, optional for EVM
*/
export type Chain = EvmChain | SolanaChain | AptosChain | ChromiaChain | FuelChain;
export type Chain = EvmChain | SolanaChain | AptosChain | ChromiaChain | FuelChain | SuiChain;

export type SuiChain = {
type: "sui";
};

export type EvmChain = {
type: "evm";
Expand Down
33 changes: 33 additions & 0 deletions typescript/packages/wallets/sui/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "@goat-sdk/wallet-sui",
"version": "0.2.8",
"sideEffects": false,
"files": ["dist/**/*", "README.md", "package.json"],
"scripts": {
"build": "tsup",
"clean": "rm -rf dist",
"test": "vitest run --passWithNoTests"
},
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"dependencies": {
"@goat-sdk/core": "workspace:*",
"@mysten/sui": "^1.18.0",
"zod": "catalog:"
},
"peerDependencies": {
"@goat-sdk/core": "workspace:*",
"@mysten/sui": "^1.0.0"
},
"homepage": "https://ohmygoat.dev",
"repository": {
"type": "git",
"url": "git+https://github.com/goat-sdk/goat.git"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/goat-sdk/goat/issues"
},
"keywords": ["ai", "agents", "web3"]
}
64 changes: 64 additions & 0 deletions typescript/packages/wallets/sui/src/SuiKeyPairWalletClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import type { Signature } from "@goat-sdk/core";
import { SuiClient } from "@mysten/sui/client";
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
import { SuiWalletClient } from "./SuiWalletClient";
import type { SuiQuery, SuiReadResponse, SuiTransaction, TransactionResponse } from "./types";

export type SuiKeyPairWalletClientParams = {
client: SuiClient;
keypair: Ed25519Keypair;
};

export class SuiKeyPairWalletClient extends SuiWalletClient {
private keypair: Ed25519Keypair;

constructor(params: SuiKeyPairWalletClientParams) {
super({ client: params.client });
this.keypair = params.keypair;
}

/**
* Send a transaction to the Sui network.
* This method can handle any type of Sui transaction, including:
* - Token transfers
* - Smart contract interactions
* - Object management
* - Custom transaction blocks
*/
async sendTransaction(transaction: SuiTransaction): Promise<TransactionResponse> {
const result = await this.client.signAndExecuteTransaction({
transaction: transaction.transaction,
signer: this.keypair,
});

await this.client.waitForTransaction({
digest: result.digest,
});

return { hash: result.digest };
}

async read(query: SuiQuery): Promise<SuiReadResponse> {
// Use dynamic field or object read based on the query
const result = await this.client.getObject({
id: query.objectId,
options: {
showContent: true,
},
});

return {
value: result.data,
};
}

getAddress(): string {
return this.keypair.getPublicKey().toSuiAddress();
}

async signMessage(message: string): Promise<Signature> {
const signatureArray = await this.keypair.sign(new TextEncoder().encode(message));
const signature = Buffer.from(signatureArray).toString("base64");
return { signature };
}
}
53 changes: 53 additions & 0 deletions typescript/packages/wallets/sui/src/SuiWalletClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { WalletClientBase } from "@goat-sdk/core";
import type { Chain } from "@goat-sdk/core";
import type { Balance, Signature } from "@goat-sdk/core";
import { type SuiClient } from "@mysten/sui/client";

import type {
SuiQuery,
SuiReadResponse,
SuiTransaction,
SuiWalletClientCtorParams,
TransactionResponse,
} from "./types";

export abstract class SuiWalletClient extends WalletClientBase {
protected client: SuiClient;

constructor(params: SuiWalletClientCtorParams) {
super();
this.client = params.client;
}

getChain(): Chain {
return {
type: "sui",
} as const;
}

getClient() {
return this.client;
}

abstract getAddress(): string;

abstract signMessage(message: string): Promise<Signature>;

abstract sendTransaction(transaction: SuiTransaction): Promise<TransactionResponse>;

abstract read(query: SuiQuery): Promise<SuiReadResponse>;

async balanceOf(address: string): Promise<Balance> {
const balance = await this.client.getBalance({
owner: address,
});

return {
decimals: 9,
symbol: "SUI",
name: "Sui",
value: balance.totalBalance,
inBaseUnits: balance.totalBalance,
};
}
}
2 changes: 2 additions & 0 deletions typescript/packages/wallets/sui/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./SuiWalletClient";
export * from "./types";
40 changes: 40 additions & 0 deletions typescript/packages/wallets/sui/src/sendSui.plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Chain, PluginBase, createTool } from "@goat-sdk/core";
import { Transaction } from "@mysten/sui/transactions";
import { z } from "zod";
import { SuiWalletClient } from "./SuiWalletClient";

const sendSUIParametersSchema = z.object({
to: z.string().describe("The recipient's address"),
amount: z.number().describe("The amount of SUI to send"),
});

const sendSUIMethod = async (walletClient: SuiWalletClient, parameters: z.infer<typeof sendSUIParametersSchema>) => {
const { to, amount } = parameters;
const tx = new Transaction();
const [coin] = tx.splitCoins(tx.gas, [amount]);
tx.transferObjects([coin], to);
return walletClient.sendTransaction({
transaction: tx,
});
};

export class SendSUIPlugin extends PluginBase<SuiWalletClient> {
constructor() {
super("sendSUI", []);
}

supportsChain = (chain: Chain) => chain.type === "sui";

getTools(walletClient: SuiWalletClient) {
const sendTool = createTool(
{
name: "send_sui",
description: "Send SUI to an address.",
parameters: sendSUIParametersSchema,
},
// Implement the method
(parameters: z.infer<typeof sendSUIParametersSchema>) => sendSUIMethod(walletClient, parameters),
);
return [sendTool];
}
}
22 changes: 22 additions & 0 deletions typescript/packages/wallets/sui/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { SuiClient } from "@mysten/sui/client";
import { type Transaction } from "@mysten/sui/transactions";

export type SuiReadResponse = {
value: unknown;
};

export type SuiTransaction = {
0xaguspunk marked this conversation as resolved.
Show resolved Hide resolved
transaction: Transaction;
};

export type TransactionResponse = {
hash: string;
};

export type SuiQuery = {
objectId: string;
};

export type SuiWalletClientCtorParams = {
client: SuiClient;
};
6 changes: 6 additions & 0 deletions typescript/packages/wallets/sui/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "../../../tsconfig.base.json",
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
6 changes: 6 additions & 0 deletions typescript/packages/wallets/sui/tsup.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { defineConfig } from "tsup";
import { treeShakableConfig } from "../../../tsup.config.base";

export default defineConfig({
...treeShakableConfig,
});
Loading
Loading