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

Wallet tools #22

Draft
wants to merge 34 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
593b2f1
wallet tools
Dec 26, 2024
8cee39f
metadata
Dec 26, 2024
9c2ebb6
Update .gitignore and remove directory.json file
guillevalin Dec 20, 2024
2d22a85
Update build scripts to use DOWNLOAD_PREFIX and configure Cloudflare …
guillevalin Dec 20, 2024
534d30b
Enhance build workflow by adding AWS credentials configuration and im…
guillevalin Dec 20, 2024
a63d32b
Add Cloudflare R2 endpoint configuration and local build scripts
guillevalin Dec 20, 2024
4267b86
Refactor build workflow to streamline AWS credentials configuration f…
guillevalin Dec 20, 2024
c177819
Auto-build tools
actions-user Dec 20, 2024
742a9f0
Delete packages from Github
guillevalin Dec 20, 2024
5da894f
Update hash generation from md5 to sha256 in build_tool.sh
guillevalin Dec 20, 2024
9188acb
Switch hash generation from sha256 to blake3 in build_tool.sh and upd…
guillevalin Dec 20, 2024
efaf5be
Implement Shinkai Package Registry: Add initial React app structure, …
guillevalin Dec 21, 2024
9ce2245
Enhance tool metadata handling and UI:
guillevalin Dec 21, 2024
753e39f
Add npm ci command in build_tools.yaml to ensure consistent package i…
guillevalin Dec 21, 2024
2456ace
Add GitHub Actions workflow for building and uploading registry site
guillevalin Dec 21, 2024
b8d0afd
Fix comparison operator in PackageList.js to use strict equality for …
guillevalin Dec 21, 2024
abacf2a
Refactor GitHub Actions workflow: Rename build_tools job to build_sit…
guillevalin Dec 21, 2024
f0245c0
Enhance PackageList component with installation dialog and improved UI
guillevalin Dec 21, 2024
6ec36e1
Remove unused import.
guillevalin Dec 21, 2024
3eb320b
Update README.md
guillevalin Dec 21, 2024
606ead0
update
nicarq Dec 22, 2024
5965075
update
nicarq Dec 22, 2024
125d841
Moved site building to Cloudflare Pages.
guillevalin Dec 22, 2024
f538068
Change R2 bucket directory.
guillevalin Dec 22, 2024
0d41c1f
Update R2 path.
guillevalin Dec 22, 2024
4af083d
Update site title
guillevalin Dec 23, 2024
f123c4c
Add keywords and programming language metadata.
guillevalin Dec 23, 2024
28edc4a
Implement keywords and code type.
guillevalin Dec 23, 2024
c9bded9
Updated home.
guillevalin Dec 23, 2024
7073443
launcher script
acedward Dec 24, 2024
f9496d9
support for both params versions. added exec time
acedward Dec 24, 2024
2a195ae
wait 100ms
acedward Dec 24, 2024
51a586f
tools for working with mounts/files
acedward Dec 24, 2024
6575d33
merge conflicts
Dec 26, 2024
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
62 changes: 62 additions & 0 deletions tools/wallet-eth-balance/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"name": "Wallet Manager",
"description": "Manages wallet operations including fetching ETH and token balances.",
"author": "@@eduardosotomontaner.arb-sep-shinkai",
"keywords": [
"wallet",
"eth",
"token",
"balance",
"management"
],
"configurations": {
"type": "object",
"properties": {
"rpcURL": {
"type": "string",
"description": "The RPC URL for the blockchain"
},
"chain": {
"type": "string",
"description": "The blockchain chain identifier"
},
"privateKey": {
"type": "string",
"description": "The private key for the wallet"
}
},
"required": [
"rpcURL",
"chain",
"privateKey"
]
},
"parameters": {
"type": "object",
"properties": {
"address": {
"type": "string",
"description": "The wallet address to fetch the ETH balance for"
}
},
"required": [
"address"
]
},
"result": {
"type": "object",
"properties": {
"ethBalance": {
"type": "string",
"description": "The ETH balance of the specified address"
}
},
"required": [
"ethBalance"
]
},
"sqlTables": [],
"sqlQueries": [],
"tools": [],
"oauth": []
}
173 changes: 173 additions & 0 deletions tools/wallet-eth-balance/tool.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import {
createPublicClient,
createWalletClient,
http,
formatEther,
encodeFunctionData,
type Address,
type PublicClient,
type WalletClient,
type Chain,
type Hex,
type TransactionReceipt,
erc20Abi
} from 'npm:viem'
import { privateKeyToAccount, type PrivateKeyAccount } from 'npm:viem/accounts'

import { arbitrumSepolia, arbitrumNova, base, baseSepolia } from 'npm:viem/chains'

interface WalletConfig {
rpcUrl: string;
chain: Chain;
privateKey: Hex;
}

const chainsDict = {
ARBITRUM_SEPOLIA : arbitrumSepolia,
ARBITRUM_NOVA : arbitrumNova,
BASE : base,
BASE_SEPOLIA : baseSepolia,
}

interface CONFIG {
chain: keyof typeof chainsDict;
privateKey: `0x${string}`;
rpcURL: string;
}

type INPUTS = {
address: `0x${string}`;
}

type OUTPUT = {
ethBalance: string;
}

export class WalletManager {
private publicClient: PublicClient;
private account: PrivateKeyAccount;
private chain: Chain;
private address: Address;

constructor({ rpcUrl, chain, privateKey }: WalletConfig) {
this.account = privateKeyToAccount(privateKey);
this.address = this.account.address;
this.chain = chain;
this.publicClient = createPublicClient({
chain,
transport: http(rpcUrl)
});
}

private createWalletClient(): WalletClient {
return createWalletClient({
chain: this.chain,
transport: http(this.publicClient.transport.url), // Use same RPC URL
account: this.account
});
}

async getETHBalance(address: Address=this.address): Promise<string> {
const balance = await this.publicClient.getBalance({ address });
return formatEther(balance);
}

async getTokenBalance(tokenAddress: Address, walletAddress: Address=this.address): Promise<string> {
const [balance, decimals] = await Promise.all([
this.publicClient.readContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'balanceOf',
args: [walletAddress]
}),
this.publicClient.readContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'decimals'
})
]);

return (balance / 10n ** BigInt(decimals)).toString();
}

private async getTokenValue(tokenAddress: Address, amount: string | number | bigint): Promise<bigint> {
const decimals = await this.publicClient.readContract({
address: tokenAddress,
abi: erc20Abi,
functionName: 'decimals'
});
return BigInt(amount) * (10n ** BigInt(decimals));
}

async estimateGas(
tokenAddress: Address,
toAddress: Address,
amount: string | number | bigint
): Promise<bigint> {
const value = await this.getTokenValue(tokenAddress, amount);
return await this.publicClient.estimateContractGas({
address: tokenAddress,
abi: erc20Abi,
functionName: 'transfer',
args: [toAddress, value],
account: this.account.address
});
}
async sendTokens(
tokenAddress: Address,
toAddress: Address,
amount: string | number | bigint
): Promise<TransactionReceipt> {
const value = await this.getTokenValue(tokenAddress, amount);
const walletClient = this.createWalletClient();
const data = encodeFunctionData({
abi: erc20Abi,
functionName: 'transfer',
args: [toAddress, value]
});
const gasEstimate = await this.estimateGas(tokenAddress, toAddress, amount);
/*const request = await walletClient.prepareTransactionRequest({
to: tokenAddress,
account: this.account.address,
abi: erc20Abi,
chain: this.chain,
gas: gasEstimate,
data,
});*/
const tx = await walletClient.signTransaction({
to: tokenAddress,
account: this.account.address,
abi: erc20Abi,
chain: this.chain,
gas: gasEstimate,
data,
});
const hash = await this.publicClient.sendRawTransaction({
serializedTransaction: tx
});
return await this.publicClient.waitForTransactionReceipt({ hash });
}
}

const ETHBALANCE_ERROR = 'ETHBALANCE_ERROR';

export async function run(
config: CONFIG,
inputs: INPUTS
): Promise<OUTPUT> {
try {
const { address } = inputs;
if (!address) {
throw new Error('Address is required in inputs');
}
const walletManager = new WalletManager({
rpcUrl: config.rpcURL,
chain: chainsDict[config.chain],
privateKey: config.privateKey
});
const ethBalance = await walletManager.getETHBalance(address);
return { ethBalance };
} catch (error) {
throw new Error(ETHBALANCE_ERROR, { cause: error });
}
}
104 changes: 104 additions & 0 deletions tools/wallet-send-token/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
{
"name": "WalletManager",
"description": "Manages operations related to a cryptocurrency wallet including sending tokens and checking balances.",
"author": "@@eduardosotomontaner.arb-sep-shinkai",
"keywords": [
"wallet",
"cryptocurrency",
"tokens",
"ethereum"
],
"configurations": {
"type": "object",
"properties": {
"rpcUrl": {
"type": "string",
"description": "The RPC URL to connect to the blockchain"
},
"chain": {
"type": "string",
"description": "The blockchain chain to interact with"
},
"privateKey": {
"type": "string",
"description": "The private key associated with the wallet"
}
},
"required": [
"rpcUrl",
"chain",
"privateKey"
]
},
"parameters": {
"type": "object",
"properties": {
"to_address": {
"type": "string",
"description": "The address to which tokens are sent"
},
"tokenAddress": {
"type": "string",
"description": "The address of the token contract"
},
"amount": {
"type": "string",
"description": "The amount of tokens to send"
}
},
"required": [
"to_address",
"tokenAddress",
"amount"
]
},
"result": {
"type": "object",
"properties": {
"receipt": {
"type": "object",
"properties": {
"transactionHash": {
"type": "string",
"description": "The hash of the transaction"
},
"status": {
"type": "string",
"description": "The status of the transaction"
},
"gasUsed": {
"type": "integer",
"description": "The amount of gas used for the transaction"
},
"gasPrice": {
"type": "integer",
"description": "The gas price at which the transaction was executed"
},
"from": {
"type": "string",
"description": "The address of the sender"
},
"to": {
"type": "string",
"description": "The address of the receiver"
}
},
"required": [
"transactionHash",
"status",
"gasUsed",
"gasPrice",
"from",
"to"
]
}
},
"required": [
"receipt"
]
},
"sqlTables": [],
"sqlQueries": [],
"tools": [],
"oauth": []
}
Loading