diff --git a/__tests__/rpcProvider.test.ts b/__tests__/rpcProvider.test.ts index 53eede792..6c3fef393 100644 --- a/__tests__/rpcProvider.test.ts +++ b/__tests__/rpcProvider.test.ts @@ -1,4 +1,18 @@ import { getStarkKey, Signature, utils } from '@scure/starknet'; +import { hasMixin } from 'ts-mixer'; +import { + contracts, + createBlockForDevnet, + createTestProvider, + describeIfDevnet, + describeIfNotDevnet, + describeIfRpc, + describeIfTestnet, + ETHtokenAddress, + getTestAccount, + waitNextBlock, +} from './config/fixtures'; +import { initializeMatcher } from './config/schema'; import typedDataExample from '../__mocks__/typedData/baseExample.json'; import { Account, @@ -6,6 +20,7 @@ import { CallData, Contract, FeeEstimate, + LibraryError, ProviderInterface, RPC, RPCResponseParser, @@ -19,21 +34,11 @@ import { import { StarknetChainId } from '../src/global/constants'; import { felt, uint256 } from '../src/utils/calldata/cairo'; import { toBigInt, toHexString } from '../src/utils/num'; -import { - contracts, - createBlockForDevnet, - createTestProvider, - describeIfDevnet, - describeIfNotDevnet, - describeIfRpc, - describeIfTestnet, - ETHtokenAddress, - getTestAccount, - waitNextBlock, -} from './config/fixtures'; -import { initializeMatcher } from './config/schema'; -import { isBoolean } from '../src/utils/typed'; import { isVersion } from '../src/utils/provider'; +import { isBoolean } from '../src/utils/typed'; +import { RpcProvider as BaseRpcProvider } from '../src/provider/rpc'; +import { RpcProvider as ExtendedRpcProvider } from '../src/provider/extensions/default'; +import { StarknetId } from '../src/provider/extensions/starknetId'; describeIfRpc('RPCProvider', () => { let rpcProvider: RpcProvider; @@ -53,6 +58,16 @@ describeIfRpc('RPCProvider', () => { await createBlockForDevnet(); }); + test('create should be usable by the base and extended RpcProvider, but not Account', async () => { + const nodeUrl = process.env.TEST_RPC_URL; + const base = await BaseRpcProvider.create({ nodeUrl }); + const extended = await ExtendedRpcProvider.create({ nodeUrl }); + + expect(hasMixin(base, StarknetId)).toBe(false); + expect(hasMixin(extended, StarknetId)).toBe(true); + await expect(Account.create()).rejects.toThrow(LibraryError); + }); + test('detect spec version with create', async () => { const providerTest = await RpcProvider.create({ nodeUrl: process.env.TEST_RPC_URL }); const { channel } = providerTest; diff --git a/src/account/default.ts b/src/account/default.ts index e5b753e21..e1166f64a 100644 --- a/src/account/default.ts +++ b/src/account/default.ts @@ -6,7 +6,7 @@ import { UDC, ZERO, } from '../global/constants'; -import { Provider, ProviderInterface } from '../provider'; +import { LibraryError, Provider, ProviderInterface } from '../provider'; import { Signer, SignerInterface } from '../signer'; import { AccountInvocations, @@ -119,6 +119,13 @@ export class Account extends Provider implements AccountInterface { }); } + /** @deprecated @hidden */ + // The deprecation tag is meant to discourage use, not to signal future removal + // it should only be removed if the relationship with the corresponding Provider.create(...) method changes + static async create(): Promise { + throw new LibraryError('Not supported'); + } + // provided version or contract based preferred transactionVersion protected getPreferredVersion(type12: ETransactionVersion, type3: ETransactionVersion) { if (this.transactionVersion === ETransactionVersion.V3) return type3; diff --git a/src/provider/rpc.ts b/src/provider/rpc.ts index 88c65f26b..cecac5677 100644 --- a/src/provider/rpc.ts +++ b/src/provider/rpc.ts @@ -92,18 +92,22 @@ export class RpcProvider implements ProviderInterface { * auto configure channel based on provided node * leave space for other async before constructor */ - static async create(optionsOrProvider?: RpcProviderOptions) { + // NOTE: the generic T and 'this' reference are used so that the expanded class is generated when a mixin is applied + static async create( + this: { new (...args: ConstructorParameters): T }, + optionsOrProvider?: RpcProviderOptions + ): Promise { const channel = new RPC07.RpcChannel({ ...optionsOrProvider }); const spec = await channel.getSpecVersion(); if (isVersion('0.7', spec)) { - return new RpcProvider({ ...optionsOrProvider, specVersion: '0.7' }); + return new this({ ...optionsOrProvider, specVersion: '0.7' }) as T; } if (isVersion('0.8', spec)) { - return new RpcProvider({ ...optionsOrProvider, specVersion: '0.8' }); + return new this({ ...optionsOrProvider, specVersion: '0.8' }) as T; } - throw new Error('unable to detect specification version'); + throw new LibraryError('Unable to detect specification version'); } public fetch(method: string, params?: object, id: string | number = 0) {