From 8f8b0351e0a637494a4b965165e98ce7e8f0122c Mon Sep 17 00:00:00 2001 From: Ben Guidarelli Date: Sat, 25 Nov 2023 09:49:21 -0500 Subject: [PATCH] reduce some boilerplate, make it easier to access a static reference to the class instance (#164) --- core/definitions/src/attestation.ts | 2 + core/definitions/src/chain.ts | 19 +++++---- core/definitions/src/platform.ts | 24 +++++++---- core/definitions/src/protocol.ts | 16 ++++++-- core/definitions/src/protocols/core.ts | 8 +++- .../definitions/src/testing/mocks/platform.ts | 25 ++---------- examples/src/helpers/helpers.ts | 6 +-- platforms/aptos/src/address.ts | 4 +- platforms/aptos/src/platform.ts | 40 ++----------------- platforms/cosmwasm/src/platform.ts | 31 -------------- platforms/evm/src/platform.ts | 34 ---------------- platforms/solana/src/platform.ts | 39 ++---------------- 12 files changed, 60 insertions(+), 188 deletions(-) diff --git a/core/definitions/src/attestation.ts b/core/definitions/src/attestation.ts index f85323b94..6e3bed2a1 100644 --- a/core/definitions/src/attestation.ts +++ b/core/definitions/src/attestation.ts @@ -9,6 +9,8 @@ export type WormholeMessageId = { chain: Chain; emitter: UniversalAddress; sequence: SequenceId; + // TODO + vaa?: VAA; }; export function isWormholeMessageId(thing: WormholeMessageId | any): thing is WormholeMessageId { return ( diff --git a/core/definitions/src/chain.ts b/core/definitions/src/chain.ts index ba2afd45c..92e4035b5 100644 --- a/core/definitions/src/chain.ts +++ b/core/definitions/src/chain.ts @@ -8,11 +8,11 @@ import { import { TokenAddress } from "./address"; import { WormholeMessageId } from "./attestation"; -import { PlatformContext, PlatformUtils } from "./platform"; +import { PlatformContext } from "./platform"; +import { protocolIsRegistered } from "./protocol"; import { AutomaticCircleBridge, CircleBridge } from "./protocols/cctp"; import { IbcBridge } from "./protocols/ibc"; import { AutomaticTokenBridge, TokenBridge } from "./protocols/tokenBridge"; -import { protocolIsRegistered } from "./protocol"; import { RpcConnection } from "./rpc"; import { ChainConfig, SignedTx } from "./types"; @@ -24,7 +24,6 @@ export abstract class ChainContext< readonly network: N; readonly platform: PlatformContext; - readonly platformUtils: PlatformUtils; readonly chain: C; readonly config: ChainConfig; @@ -40,7 +39,6 @@ export abstract class ChainContext< constructor(chain: C, platform: PlatformContext) { this.config = platform.config[chain]; this.platform = platform; - this.platformUtils = platform.constructor as any as PlatformUtils; this.chain = this.config.key; this.network = this.config.network; } @@ -52,29 +50,30 @@ export abstract class ChainContext< // Get the number of decimals for a token async getDecimals(token: TokenAddress): Promise { - return this.platformUtils.getDecimals(this.chain, this.getRpc(), token); + return this.platform.utils().getDecimals(this.chain, this.getRpc(), token); } // Get the balance of a token for a given address async getBalance(walletAddr: string, token: TokenAddress): Promise { - return this.platformUtils.getBalance(this.chain, await this.getRpc(), walletAddr, token); + return this.platform.utils().getBalance(this.chain, await this.getRpc(), walletAddr, token); } async getLatestBlock(): Promise { - return this.platformUtils.getLatestBlock(this.getRpc()); + return this.platform.utils().getLatestBlock(this.getRpc()); } + async getLatestFinalizedBlock(): Promise { - return this.platformUtils.getLatestFinalizedBlock(this.getRpc()); + return this.platform.utils().getLatestFinalizedBlock(this.getRpc()); } // Get details about the transaction async parseTransaction(txid: string): Promise { - return this.platform.parseTransaction(this.chain, await this.getRpc(), txid); + return this.platform.parseWormholeMessages(this.chain, await this.getRpc(), txid); } // Send a transaction and wait for it to be confirmed async sendWait(stxns: SignedTx): Promise { - return this.platformUtils.sendWait(this.chain, await this.getRpc(), stxns); + return this.platform.utils().sendWait(this.chain, await this.getRpc(), stxns); } // diff --git a/core/definitions/src/platform.ts b/core/definitions/src/platform.ts index 1383a3f07..7e43d530b 100644 --- a/core/definitions/src/platform.ts +++ b/core/definitions/src/platform.ts @@ -5,12 +5,13 @@ import { PlatformToChains, ProtocolName, } from "@wormhole-foundation/sdk-base"; +import { WormholeCore } from "."; +import { TokenAddress } from "./address"; import { WormholeMessageId } from "./attestation"; import { ChainContext } from "./chain"; +import { create } from "./protocol"; import { RpcConnection } from "./rpc"; -import { TokenAddress } from "./address"; import { Balances, ChainsConfig, SignedTx, TokenId, TxHash } from "./types"; -import { ProtocolInitializer } from "./protocol"; // PlatformUtils represents the _static_ attributes available on // the PlatformContext Class @@ -21,9 +22,6 @@ export interface PlatformUtils { // Initialize a new PlatformContext object new (network: N, config?: ChainsConfig): PlatformContext; - // Get a protocol name - getProtocolInitializer(protocol: PN): ProtocolInitializer; - // Check if this chain is supported by this platform // Note: purposely not adding generic parameters isSupportedChain(chain: Chain): boolean; @@ -89,6 +87,11 @@ export abstract class PlatformContext { readonly config: ChainsConfig, ) {} + // provides access to the static attributes of the PlatformContext class + utils(): PlatformUtils { + return this.constructor as any; + } + // Create a _new_ RPC Connection abstract getRpc>(chain: C): RpcConnection

; @@ -96,12 +99,17 @@ export abstract class PlatformContext { abstract getChain>(chain: C): ChainContext; // Create a new Protocol Client instance by protocol name - abstract getProtocol(protocol: PN, rpc: RpcConnection

): Promise; + getProtocol(protocol: PN, rpc: RpcConnection

): Promise { + return create(this.utils()._platform, protocol, rpc, this.config); + } // Look up transaction logs and parse out Wormhole messages - abstract parseTransaction>( + async parseWormholeMessages>( chain: C, rpc: RpcConnection

, txid: TxHash, - ): Promise; + ): Promise { + const wc: WormholeCore = await this.getProtocol("WormholeCore", rpc); + return wc.parseTransaction(txid); + } } diff --git a/core/definitions/src/protocol.ts b/core/definitions/src/protocol.ts index 370796001..f4863c350 100644 --- a/core/definitions/src/protocol.ts +++ b/core/definitions/src/protocol.ts @@ -1,10 +1,10 @@ import { Chain, - isChain, + Network, Platform, - chainToPlatform, ProtocolName, - Network, + chainToPlatform, + isChain, } from "@wormhole-foundation/sdk-base"; import { RpcConnection } from "./rpc"; import { ChainsConfig } from "./types"; @@ -76,3 +76,13 @@ export function getProtocolInitializer

; } + +export const create = ( + platform: P, + protocol: PN, + rpc: RpcConnection

, + config: ChainsConfig, +): Promise => { + const pctr = getProtocolInitializer(platform, protocol); + return pctr.fromRpc(rpc, config) as Promise; +}; diff --git a/core/definitions/src/protocols/core.ts b/core/definitions/src/protocols/core.ts index 6289fa0a8..6e7dc832f 100644 --- a/core/definitions/src/protocols/core.ts +++ b/core/definitions/src/protocols/core.ts @@ -4,10 +4,14 @@ import { AccountAddress } from "../address"; import { WormholeMessageId } from "../attestation"; import { TxHash } from "../types"; import { UnsignedTransaction } from "../unsignedTransaction"; -export interface WormholeCore> { +export interface WormholeCore< + N extends Network, + P extends Platform, + C extends PlatformToChains

, +> { publishMessage( sender: AccountAddress, - message: string | Uint8Array + message: string | Uint8Array, ): AsyncGenerator>; parseTransaction(txid: TxHash): Promise; // TODO: events? diff --git a/core/definitions/src/testing/mocks/platform.ts b/core/definitions/src/testing/mocks/platform.ts index 5d953323b..35f0197ec 100644 --- a/core/definitions/src/testing/mocks/platform.ts +++ b/core/definitions/src/testing/mocks/platform.ts @@ -13,8 +13,6 @@ import { RpcConnection, TokenAddress, TokenId, - TxHash, - WormholeMessageId, } from "../.."; import { MockChain } from "./chain"; import { MockRpc } from "./rpc"; @@ -27,22 +25,17 @@ export function mockPlatformFactory( static _platform: P = platform; constructor(network: N, _config?: ChainsConfig) { super(network, _config ? _config : config); - this.network = network; } } // @ts-ignore - return ConcreteMockPlatform; + return ConcreteMockPlatform; } // Note: don't use this directly, instead create a ConcreteMockPlatform with the // mockPlatformFactory -export class MockPlatform implements PlatformContext { - network: N; - config: ChainsConfig; - +export class MockPlatform extends PlatformContext { constructor(network: N, config: ChainsConfig) { - this.network = network; - this.config = config; + super(network, config); } static getProtocol(protocol: PN): T { @@ -129,18 +122,6 @@ export class MockPlatform implements Plat return 0n; } - async parseTransaction>( - chain: C, - rpc: RpcConnection

, - txid: TxHash, - ): Promise { - throw new Error("Method not implemented"); - } - - getProtocol(protocol: PN): T { - throw new Error("Method not implemented."); - } - getDecimals>( chain: C, rpc: RpcConnection

, diff --git a/examples/src/helpers/helpers.ts b/examples/src/helpers/helpers.ts index 0384a7bab..c05cd6f61 100644 --- a/examples/src/helpers/helpers.ts +++ b/examples/src/helpers/helpers.ts @@ -44,8 +44,8 @@ export async function getStuff< C extends PlatformToChains

, >(chain: ChainContext): Promise> { let signer: Signer; - - switch (chain.platformUtils._platform) { + const platform = chain.platform.utils()._platform; + switch (platform) { case "Solana": signer = await getSolanaSigner(await chain.getRpc(), getEnv("SOL_PRIVATE_KEY")); break; @@ -56,7 +56,7 @@ export async function getStuff< signer = await getEvmSigner(await chain.getRpc(), getEnv("ETH_PRIVATE_KEY")); break; default: - throw new Error("Unrecognized platform: " + chain.platformUtils._platform); + throw new Error("Unrecognized platform: " + platform); } return { chain, signer, address: nativeChainAddress(chain.chain, signer.address()) }; diff --git a/platforms/aptos/src/address.ts b/platforms/aptos/src/address.ts index 30dbe8d54..4c7004d7b 100644 --- a/platforms/aptos/src/address.ts +++ b/platforms/aptos/src/address.ts @@ -96,6 +96,4 @@ export class AptosAddress implements Address { } } -try { - registerNative("Aptos", AptosAddress); -} catch {} +registerNative("Aptos", AptosAddress); diff --git a/platforms/aptos/src/platform.ts b/platforms/aptos/src/platform.ts index 08b0e8193..5ed34df56 100644 --- a/platforms/aptos/src/platform.ts +++ b/platforms/aptos/src/platform.ts @@ -1,14 +1,4 @@ -import { - Chain, - Network, - PlatformContext, - ProtocolImplementation, - ProtocolInitializer, - ProtocolName, - WormholeCore, - WormholeMessageId, - getProtocolInitializer, -} from "@wormhole-foundation/connect-sdk"; +import { Chain, Network, PlatformContext } from "@wormhole-foundation/connect-sdk"; import { AptosClient } from "aptos"; import { AptosChain } from "./chain"; import { AptosChains, AptosPlatformType, _platform } from "./types"; @@ -43,22 +33,6 @@ export class AptosPlatform extends PlatformContext( - protocol: PN, - rpc: AptosClient, - ): Promise> { - return AptosPlatform.getProtocolInitializer(protocol).fromRpc(rpc, this.config); - } - - async parseTransaction( - chain: C, - rpc: AptosClient, - tx: string, - ): Promise { - const core: WormholeCore = await this.getProtocol("WormholeCore", rpc); - return core.parseTransaction(tx); - } - static nativeTokenId(network: N, chain: C): TokenId { if (!this.isSupportedChain(chain)) throw new Error(`invalid chain: ${chain}`); return nativeChainAddress(chain, APTOS_COIN); @@ -80,7 +54,7 @@ export class AptosPlatform extends PlatformContext extends PlatformContext extends PlatformContext extends PlatformContext( - protocol: PN, - ): ProtocolInitializer { - return getProtocolInitializer(this._platform, protocol); - } } diff --git a/platforms/cosmwasm/src/platform.ts b/platforms/cosmwasm/src/platform.ts index 48f6a1770..6d8b1ab0b 100644 --- a/platforms/cosmwasm/src/platform.ts +++ b/platforms/cosmwasm/src/platform.ts @@ -13,15 +13,9 @@ import { ChainsConfig, Network, PlatformContext, - ProtocolImplementation, - ProtocolInitializer, - ProtocolName, SignedTx, TxHash, - WormholeCore, - WormholeMessageId, decimals, - getProtocolInitializer, nativeChainIds, networkPlatformConfigs, } from "@wormhole-foundation/connect-sdk"; @@ -67,25 +61,6 @@ export class CosmwasmPlatform extends PlatformContext( - protocol: PN, - rpc: CosmWasmClient, - ): Promise> { - return CosmwasmPlatform.getProtocolInitializer(protocol).fromRpc(rpc, this.config); - } - - async parseTransaction( - chain: C, - rpc: CosmWasmClient, - txid: TxHash, - ): Promise { - const core: WormholeCore = await this.getProtocol( - "WormholeCore", - rpc, - ); - return core.parseTransaction(txid); - } - static getQueryClient = (rpc: CosmWasmClient): QueryClient & BankExtension & IbcExtension => { // @ts-ignore -- access private attribute const tmClient: TendermintClient = rpc.getTmClient()!; @@ -225,10 +200,4 @@ export class CosmwasmPlatform extends PlatformContext( - protocol: PN, - ): ProtocolInitializer { - return getProtocolInitializer(this._platform, protocol); - } } diff --git a/platforms/evm/src/platform.ts b/platforms/evm/src/platform.ts index efdc2efb6..4e180437d 100644 --- a/platforms/evm/src/platform.ts +++ b/platforms/evm/src/platform.ts @@ -4,18 +4,12 @@ import { ChainsConfig, Network, PlatformContext, - ProtocolImplementation, - ProtocolInitializer, - ProtocolName, SignedTx, TokenId, TxHash, - WormholeCore, - WormholeMessageId, chainToPlatform, decimals, encoding, - getProtocolInitializer, nativeChainAddress, nativeChainIds, networkPlatformConfigs, @@ -55,28 +49,6 @@ export class EvmPlatform extends PlatformContext< throw new Error('No configuration available for chain: ' + chain); } - async getProtocol( - protocol: PN, - rpc: Provider, - ): Promise> { - return EvmPlatform.getProtocolInitializer(protocol).fromRpc( - rpc, - this.config, - ); - } - - async parseTransaction( - chain: C, - rpc: Provider, - txid: TxHash, - ): Promise { - const wc: WormholeCore = await this.getProtocol( - 'WormholeCore', - rpc, - ); - return wc.parseTransaction(txid); - } - static nativeTokenId( network: N, chain: C, @@ -209,10 +181,4 @@ export class EvmPlatform extends PlatformContext< throw new Error(`No token implementation available for: ${address}`); return ti; } - - static getProtocolInitializer( - protocol: PN, - ): ProtocolInitializer { - return getProtocolInitializer(this._platform, protocol); - } } diff --git a/platforms/solana/src/platform.ts b/platforms/solana/src/platform.ts index 848abfd8c..1bac17ec3 100644 --- a/platforms/solana/src/platform.ts +++ b/platforms/solana/src/platform.ts @@ -4,17 +4,11 @@ import { ChainsConfig, Network, PlatformContext, - ProtocolImplementation, - ProtocolInitializer, - ProtocolName, SignedTx, TokenId, TxHash, - WormholeCore, - WormholeMessageId, chainToPlatform, decimals, - getProtocolInitializer, nativeChainAddress, nativeChainIds, networkPlatformConfigs, @@ -67,27 +61,6 @@ export class SolanaPlatform extends PlatformContext< throw new Error('No configuration available for chain: ' + chain); } - async getProtocol( - protocol: PN, - rpc: Connection, - ): Promise> { - return SolanaPlatform.getProtocolInitializer(protocol).fromRpc( - rpc, - this.config, - ); - } - async parseTransaction( - chain: C, - rpc: Connection, - tx: string, - ): Promise { - const wc: WormholeCore = await this.getProtocol( - 'WormholeCore', - rpc, - ); - return wc.parseTransaction(tx); - } - static nativeTokenId( network: N, chain: C, @@ -216,7 +189,8 @@ export class SolanaPlatform extends PlatformContext< } static async getLatestFinalizedBlock(rpc: Connection): Promise { - return await rpc.getSlot(rpc.commitment); + throw new Error('Not implemented'); + //return await rpc.getSlot(rpc.commitment); } static chainFromChainId(genesisHash: string): [Network, SolanaChains] { @@ -236,14 +210,7 @@ export class SolanaPlatform extends PlatformContext< } static async chainFromRpc(rpc: Connection): Promise<[Network, SolanaChains]> { - const conn = rpc as Connection; - const gh = await conn.getGenesisHash(); + const gh = await rpc.getGenesisHash(); return SolanaPlatform.chainFromChainId(gh); } - - static getProtocolInitializer( - protocol: PN, - ): ProtocolInitializer { - return getProtocolInitializer(this._platform, protocol); - } }