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

feat: add new RPC starkNet_addAccount #474

Merged
merged 24 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
797861f
feat: add account service
stanleyyconsensys Jan 7, 2025
36358e1
chore: fix lint
stanleyyconsensys Jan 7, 2025
2dc68ae
chore: update account contract discovery logic
stanleyyconsensys Jan 8, 2025
17b25fc
fix: code comment
stanleyyconsensys Jan 8, 2025
cc1efa4
chore: add discovery logic description
stanleyyconsensys Jan 8, 2025
a31b9c0
fix: lint
stanleyyconsensys Jan 8, 2025
fa288a4
feat: add account service factory
stanleyyconsensys Jan 9, 2025
f216dfb
fix: rename deployPayload
stanleyyconsensys Jan 9, 2025
40d3113
Merge branch 'feat/add-account-service-factory' into refactor/adopt-a…
stanleyyconsensys Jan 9, 2025
871156b
chore: adopt account discovery in RPCs
stanleyyconsensys Jan 9, 2025
21952f3
chore: update execute txn test
stanleyyconsensys Jan 9, 2025
4ec0c4f
fix: execute test
stanleyyconsensys Jan 9, 2025
883a3e6
fix: account discovery bug
stanleyyconsensys Jan 9, 2025
c92750a
fix: discovery logic
stanleyyconsensys Jan 9, 2025
5bc7498
feat: add `AddAccount` RPC
stanleyyconsensys Jan 10, 2025
0ebb0fe
feat: add max account create limit
stanleyyconsensys Jan 10, 2025
d2274af
fix: add `isMaxAccountLimitExceeded` unit test
stanleyyconsensys Jan 10, 2025
2cb0633
fix: account deploy require result
stanleyyconsensys Jan 13, 2025
f579332
Merge branch 'refactor/adopt-account-discovery' into feat/add-account…
stanleyyconsensys Jan 13, 2025
a6e56b2
fix: add some detail comment on contract discovery
stanleyyconsensys Jan 14, 2025
cf01c6c
fix: comments on test title
stanleyyconsensys Jan 14, 2025
006284b
Merge branch 'feat/enable-multiple-accounts' into refactor/adopt-acco…
khanti42 Jan 14, 2025
2f37260
Merge branch 'refactor/adopt-account-discovery' into feat/add-account…
khanti42 Jan 14, 2025
658df82
Merge branch 'feat/enable-multiple-accounts' into feat/add-account-rpc
stanleyyconsensys Jan 14, 2025
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
7 changes: 7 additions & 0 deletions packages/starknet-snap/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ export type SnapConfig = {
txnsInLastNumOfDays: number;
};
};
account: {
maxAccountToCreate: number;
};
};

export enum DataClient {
Expand All @@ -61,6 +64,10 @@ export const Config: SnapConfig = {
},
},

account: {
maxAccountToCreate: 2,
},

// eslint-disable-next-line no-restricted-globals
rpcApiKey: process.env.DIN_API_KEY ?? '',

Expand Down
7 changes: 7 additions & 0 deletions packages/starknet-snap/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import type {
GetAddrFromStarkNameParams,
GetTransactionStatusParams,
ListTransactionsParams,
AddAccountParams,
} from './rpcs';
import {
displayPrivateKey,
Expand All @@ -53,6 +54,7 @@ import {
getAddrFromStarkName,
getTransactionStatus,
listTransactions,
addAccount,
} from './rpcs';
import { signDeployAccountTransaction } from './signDeployAccountTransaction';
import type {
Expand Down Expand Up @@ -279,6 +281,11 @@ export const onRpcRequest: OnRpcRequestHandler = async ({
apiParams.requestParams as unknown as GetAddrFromStarkNameParams,
);

case RpcMethod.AddAccount:
return await addAccount.execute(
requestParams as unknown as AddAccountParams,
);

default:
throw new MethodNotFoundError() as unknown as Error;
}
Expand Down
7 changes: 7 additions & 0 deletions packages/starknet-snap/src/rpcs/__tests__/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,17 @@ export async function setupAccountController({
'deriveAccountByAddress',
);

const deriveAccountByIndexSpy = jest.spyOn(
AccountService.prototype,
'deriveAccountByIndex',
);

deriveAccountByAddressSpy.mockResolvedValue(account);
deriveAccountByIndexSpy.mockResolvedValue(account);

return {
deriveAccountByAddressSpy,
deriveAccountByIndexSpy,
isRequireDeploySpy,
isRequireUpgradeSpy,
isDeploySpy,
Expand Down
48 changes: 48 additions & 0 deletions packages/starknet-snap/src/rpcs/add-account.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { constants } from 'starknet';

import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants';
import { InvalidRequestParamsError } from '../utils/exceptions';
import { setupAccountController } from './__tests__/helper';
import { addAccount } from './add-account';
import type { AddAccountParams } from './add-account';

jest.mock('../utils/snap');
jest.mock('../utils/logger');

describe('AddAccountRpc', () => {
const network = STARKNET_SEPOLIA_TESTNET_NETWORK;

const setupAddAccountTest = async () => {
// Although `AddAccountRpc` does not inherit `AccountRpcController`,
// but we can still use `setupAccountController` to mock the `AccountService`.
const { account, deriveAccountByIndexSpy } = await setupAccountController(
{},
);

const request = {
chainId: network.chainId as unknown as constants.StarknetChainId,
};

return {
deriveAccountByIndexSpy,
account,
request,
};
};

it('add an `Account`', async () => {
const { account, request, deriveAccountByIndexSpy } =
await setupAddAccountTest();

const result = await addAccount.execute(request);

expect(result).toStrictEqual(await account.serialize());
expect(deriveAccountByIndexSpy).toHaveBeenCalled();
});

it('throws `InvalidRequestParamsError` when request parameter is not correct', async () => {
await expect(
addAccount.execute({} as unknown as AddAccountParams),
).rejects.toThrow(InvalidRequestParamsError);
});
});
46 changes: 46 additions & 0 deletions packages/starknet-snap/src/rpcs/add-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { type Infer } from 'superstruct';

import { BaseRequestStruct, AccountStruct } from '../utils';
import { createAccountService } from '../utils/factory';
import { ChainRpcController } from './abstract/chain-rpc-controller';

export const AddAccountRequestStruct = BaseRequestStruct;

export const AddAccountResponseStruct = AccountStruct;

export type AddAccountParams = Infer<typeof AddAccountRequestStruct>;

export type AddAccountResponse = Infer<typeof AddAccountResponseStruct>;

/**
* The RPC handler to get a active account by network.
*/
export class AddAccountRpc extends ChainRpcController<
AddAccountParams,
AddAccountResponse
> {
protected requestStruct = AddAccountRequestStruct;

protected responseStruct = AddAccountResponseStruct;

/**
* Execute the get active account request handler.
*
* @param params - The parameters of the request.
* @param params.chainId - The chain id of the network.
* @returns A promise that resolves to an active account.
*/
protected async handleRequest(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
params: AddAccountParams,
): Promise<AddAccountResponse> {
const accountService = createAccountService(this.network);

const account = await accountService.deriveAccountByIndex();

// TODO: after derive an account, we should store it as a active account.
return account.serialize() as unknown as AddAccountResponse;
}
}

export const addAccount = new AddAccountRpc();
1 change: 1 addition & 0 deletions packages/starknet-snap/src/rpcs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ export * from './watch-asset';
export * from './get-addr-from-starkname';
export * from './get-transaction-status';
export * from './list-transactions';
export * from './add-account';
36 changes: 34 additions & 2 deletions packages/starknet-snap/src/state/__tests__/helper.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { constants } from 'starknet';
import { constants } from 'starknet';

import { generateAccounts, type StarknetAccount } from '../../__tests__/helper';
import type {
Expand All @@ -12,6 +12,7 @@ import {
STRK_SEPOLIA_TESTNET,
} from '../../utils/constants';
import * as snapHelper from '../../utils/snap';
import { AccountStateManager } from '../account-state-manager';
import { NetworkStateManager } from '../network-state-manager';
import { TransactionRequestStateManager } from '../request-state-manager';
import { TokenStateManager } from '../token-state-manager';
Expand All @@ -27,6 +28,14 @@ export const mockAcccounts = async (
return generateAccounts(chainId, cnt);
};

export const generateTestnetAccounts = async (count?: number) => {
return await mockAcccounts(constants.StarknetChainId.SN_SEPOLIA, count);
};

export const generateMainnetAccounts = async (count?: number) => {
return await mockAcccounts(constants.StarknetChainId.SN_MAIN, count);
};

export const mockState = async ({
accounts,
tokens,
Expand All @@ -47,7 +56,7 @@ export const mockState = async ({
const getDataSpy = jest.spyOn(snapHelper, 'getStateData');
const setDataSpy = jest.spyOn(snapHelper, 'setStateData');
const state = {
accContracts: accounts,
accContracts: accounts ?? [],
erc20Tokens: tokens ?? [],
networks: networks ?? [],
transactions: transactions ?? [],
Expand Down Expand Up @@ -78,6 +87,29 @@ export const mockTokenStateManager = () => {
};
};

export const mockAccountStateManager = () => {
const getAccountSpy = jest.spyOn(AccountStateManager.prototype, 'getAccount');
const getNextIndexSpy = jest.spyOn(
AccountStateManager.prototype,
'getNextIndex',
);
const upsertAccountSpy = jest.spyOn(
AccountStateManager.prototype,
'upsertAccount',
);
const isMaxAccountLimitExceededSpy = jest.spyOn(
AccountStateManager.prototype,
'isMaxAccountLimitExceeded',
);

return {
getAccountSpy,
getNextIndexSpy,
upsertAccountSpy,
isMaxAccountLimitExceededSpy,
};
};

export const mockTransactionStateManager = () => {
const removeTransactionsSpy = jest.spyOn(
TransactionStateManager.prototype,
Expand Down
Loading
Loading