Skip to content

Commit 99acefa

Browse files
authored
feat(contract_manager): impl contract manager for ton (#2076)
* impl contract manager for ton * precommit * add more functions * finish up contract manager * fix sdk * address comments * precommit
1 parent c720bf1 commit 99acefa

File tree

20 files changed

+614
-81
lines changed

20 files changed

+614
-81
lines changed

contract_manager/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@
3636
"@pythnetwork/pyth-sdk-solidity": "workspace:^",
3737
"@pythnetwork/pyth-starknet-js": "^0.2.1",
3838
"@pythnetwork/pyth-sui-js": "workspace:*",
39+
"@pythnetwork/pyth-ton-js": "workspace:*",
3940
"@pythnetwork/solana-utils": "workspace:^",
4041
"@pythnetwork/xc-admin-common": "workspace:*",
4142
"@solana/web3.js": "^1.73.0",
4243
"@sqds/mesh": "^1.0.6",
44+
"@ton/crypto": "^3.3.0",
45+
"@ton/ton": "^15.1.0",
4346
"@types/yargs": "^17.0.32",
4447
"aptos": "^1.5.0",
4548
"axios": "^0.24.0",

contract_manager/src/chains.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ import { TokenId } from "./token";
2626
import { BN, Provider, Wallet, WalletUnlocked } from "fuels";
2727
import { FUEL_ETH_ASSET_ID } from "@pythnetwork/pyth-fuel-js";
2828
import { Contract, RpcProvider, Signer, ec, shortString } from "starknet";
29+
import {
30+
TonClient,
31+
WalletContractV4,
32+
ContractProvider,
33+
Address,
34+
OpenedContract,
35+
Sender,
36+
} from "@ton/ton";
37+
import { keyPairFromSeed } from "@ton/crypto";
38+
import { PythContract } from "@pythnetwork/pyth-ton-js";
2939

3040
export type ChainConfig = Record<string, string> & {
3141
mainnet: boolean;
@@ -738,3 +748,103 @@ export class StarknetChain extends Chain {
738748
return new RpcProvider({ nodeUrl: this.rpcUrl });
739749
}
740750
}
751+
752+
export class TonChain extends Chain {
753+
static type = "TonChain";
754+
755+
constructor(
756+
id: string,
757+
mainnet: boolean,
758+
wormholeChainName: string,
759+
nativeToken: TokenId | undefined,
760+
public rpcUrl: string
761+
) {
762+
super(id, mainnet, wormholeChainName, nativeToken);
763+
}
764+
765+
async getClient(): Promise<TonClient> {
766+
// add apiKey if facing rate limit
767+
const client = new TonClient({
768+
endpoint: this.rpcUrl,
769+
});
770+
return client;
771+
}
772+
773+
async getContract(address: string): Promise<OpenedContract<PythContract>> {
774+
const client = await this.getClient();
775+
const contract = client.open(
776+
PythContract.createFromAddress(Address.parse(address))
777+
);
778+
return contract;
779+
}
780+
781+
async getContractProvider(address: string): Promise<ContractProvider> {
782+
const client = await this.getClient();
783+
return client.provider(Address.parse(address));
784+
}
785+
786+
async getWallet(privateKey: PrivateKey): Promise<WalletContractV4> {
787+
const keyPair = keyPairFromSeed(Buffer.from(privateKey, "hex"));
788+
return WalletContractV4.create({
789+
publicKey: keyPair.publicKey,
790+
workchain: 0,
791+
});
792+
}
793+
794+
async getSender(privateKey: PrivateKey): Promise<Sender> {
795+
const client = await this.getClient();
796+
const keyPair = keyPairFromSeed(Buffer.from(privateKey, "hex"));
797+
const wallet = WalletContractV4.create({
798+
publicKey: keyPair.publicKey,
799+
workchain: 0,
800+
});
801+
const provider = client.open(wallet);
802+
return provider.sender(keyPair.secretKey);
803+
}
804+
805+
/**
806+
* Returns the payload for a governance contract upgrade instruction for contracts deployed on this chain
807+
* @param digest hex string of the 32 byte digest for the new package without the 0x prefix
808+
*/
809+
generateGovernanceUpgradePayload(digest: string): Buffer {
810+
// This might throw an error because the Fuel contract doesn't support upgrades yet (blocked on Fuel releasing Upgradeability standard)
811+
return new UpgradeContract256Bit(this.wormholeChainName, digest).encode();
812+
}
813+
814+
getType(): string {
815+
return TonChain.type;
816+
}
817+
818+
toJson(): KeyValueConfig {
819+
return {
820+
id: this.id,
821+
wormholeChainName: this.wormholeChainName,
822+
mainnet: this.mainnet,
823+
rpcUrl: this.rpcUrl,
824+
type: TonChain.type,
825+
};
826+
}
827+
828+
static fromJson(parsed: ChainConfig): TonChain {
829+
if (parsed.type !== TonChain.type) throw new Error("Invalid type");
830+
return new TonChain(
831+
parsed.id,
832+
parsed.mainnet,
833+
parsed.wormholeChainName,
834+
parsed.nativeToken,
835+
parsed.rpcUrl
836+
);
837+
}
838+
839+
async getAccountAddress(privateKey: PrivateKey): Promise<string> {
840+
const wallet = await this.getWallet(privateKey);
841+
return wallet.address.toString();
842+
}
843+
844+
async getAccountBalance(privateKey: PrivateKey): Promise<number> {
845+
const wallet = await this.getWallet(privateKey);
846+
const provider = await this.getContractProvider(wallet.address.toString());
847+
const balance = await wallet.getBalance(provider);
848+
return Number(balance) / 10 ** 9;
849+
}
850+
}

contract_manager/src/contracts/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ export * from "./fuel";
55
export * from "./sui";
66
export * from "./wormhole";
77
export * from "./evm_abis";
8+
export * from "./ton";

0 commit comments

Comments
 (0)