GOAT aims to support as many chains as possible. If your chain is not supported you can open a PR to add it.

PR to support a new chain

Here are the changes you need to make to support a new chain:

1

Add your chain to the Chain.ts file in the core package.

/**
 * @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 | MyAwesomeChain;

export type MyAwesomeChain = {
    type: "my-awesome-chain";
};
2

Create a new package in the wallets directory with the name of your chain (e.g. my-awesome-chain) or copy an existing one (e.g. evm). In this package you will define the abstract class for your chain’s wallet client which will extend the WalletClientBase class defined in the core package.

WalletClientBase only includes the methods that are supported by all chains such as:

  1. getAddress
  2. getChain
  3. signMessage
  4. balanceOf

As well as includes the getCoreTools method which returns the core tools for the chain.

export abstract class MyAwesomeChainWalletClient extends WalletClientBase {
    // Add your chain's methods here
    abstract getChain(): MyAwesomeChain;
    sendTransaction: (transaction: AwesomeChainTransaction) => Promise<Transaction>;
    read: (query: AwesomeChainQuery) => Promise<AwesomeChainResponse>;
}
3

Create a plugin to allow sending your native token to a wallet. Create a file in the same package as your wallet client and create a new file like send<native-token>.plugin.ts.

Implement the core plugin.

export class SendAWESOMETOKENPlugin extends PluginBase<MyAwesomeChainWalletClient> {
    constructor() {
        super("sendAWESOMETOKEN", []);
    }

    supportsChain = (chain: Chain) => chain.type === "my-awesome-chain";

    getTools(walletClient: MyAwesomeChainWalletClient) {
        const sendTool = createTool(
            {
                name: `send_myawesometoken`,
                description: `Send MYAWESOMETOKEN to an address.`,
                parameters: sendAWESOMETOKENParametersSchema, // Define the parameters schema
            },
            // Implement the method
            (parameters: z.infer<typeof sendAWESOMETOKENParametersSchema>) => sendAWESOMETOKENMethod(walletClient, parameters),
        );
        return [sendTool];
    }
}
4

Extend your abstract class with the methods you need to implement and create your first wallet client! (e.g MyAwesomeChainKeyPairWalletClient)

export class MyAwesomeChainKeyPairWalletClient extends MyAwesomeChainWalletClient {
    // Implement the methods here
}

// Export the wallet client with a factory function
export const myAwesomeChain = () => new MyAwesomeChainKeyPairWalletClient();
5

And you’re done! Now you can go and implement other wallet clients and plugins for your chain!