-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: revamp
starkNet_signDeclareTransaction
(#333)
* refactor: revamp sign delcare transaction * chore: add superstruct test * chore: update get-starknet interface * chore: restrict tx version to v3 and v2
- Loading branch information
1 parent
b393fe8
commit d7708da
Showing
9 changed files
with
509 additions
and
228 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export * from './signMessage'; | ||
export * from './displayPrivateKey'; | ||
export * from './signTransaction'; | ||
export * from './sign-declare-transaction'; | ||
export * from './verify-signature'; |
134 changes: 134 additions & 0 deletions
134
packages/starknet-snap/src/rpcs/sign-declare-transaction.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import { | ||
InvalidParamsError, | ||
UserRejectedRequestError, | ||
} from '@metamask/snaps-sdk'; | ||
import type { DeclareSignerDetails } from 'starknet'; | ||
import { constants } from 'starknet'; | ||
|
||
import type { SnapState } from '../types/snapState'; | ||
import { toJson } from '../utils'; | ||
import { STARKNET_SEPOLIA_TESTNET_NETWORK } from '../utils/constants'; | ||
import * as starknetUtils from '../utils/starknetUtils'; | ||
import { | ||
mockAccount, | ||
prepareMockAccount, | ||
prepareConfirmDialog, | ||
} from './__tests__/helper'; | ||
import { signDeclareTransaction } from './sign-declare-transaction'; | ||
import type { SignDeclareTransactionParams } from './sign-declare-transaction'; | ||
|
||
jest.mock('../utils/snap'); | ||
jest.mock('../utils/logger'); | ||
|
||
describe('signDeclareTransaction', () => { | ||
const state: SnapState = { | ||
accContracts: [], | ||
erc20Tokens: [], | ||
networks: [STARKNET_SEPOLIA_TESTNET_NETWORK], | ||
transactions: [], | ||
}; | ||
|
||
const createRequest = ( | ||
chainId: constants.StarknetChainId, | ||
address: string, | ||
) => ({ | ||
details: { | ||
classHash: | ||
'0x025ec026985a3bf9d0cc1fe17326b245dfdc3ff89b8fde106542a3ea56c5a918', | ||
senderAddress: address, | ||
chainId, | ||
version: constants.TRANSACTION_VERSION.V2, | ||
maxFee: 0, | ||
nonce: 0, | ||
}, | ||
address, | ||
chainId, | ||
}); | ||
|
||
it('signs message correctly', async () => { | ||
const chainId = constants.StarknetChainId.SN_SEPOLIA; | ||
const account = await mockAccount(chainId); | ||
|
||
prepareMockAccount(account, state); | ||
prepareConfirmDialog(); | ||
|
||
const request = createRequest(chainId, account.address); | ||
|
||
const expectedResult = await starknetUtils.signDeclareTransaction( | ||
account.privateKey, | ||
request.details as unknown as DeclareSignerDetails, | ||
); | ||
|
||
const result = await signDeclareTransaction.execute(request); | ||
|
||
expect(result).toStrictEqual(expectedResult); | ||
}); | ||
|
||
it('renders confirmation dialog', async () => { | ||
const chainId = constants.StarknetChainId.SN_SEPOLIA; | ||
const account = await mockAccount(chainId); | ||
|
||
prepareMockAccount(account, state); | ||
const { confirmDialogSpy } = prepareConfirmDialog(); | ||
|
||
const request = createRequest(chainId, account.address); | ||
|
||
await signDeclareTransaction.execute(request); | ||
|
||
const calls = confirmDialogSpy.mock.calls[0][0]; | ||
expect(calls).toStrictEqual([ | ||
{ type: 'heading', value: 'Do you want to sign this transaction?' }, | ||
{ | ||
type: 'row', | ||
label: 'Network', | ||
value: { | ||
value: STARKNET_SEPOLIA_TESTNET_NETWORK.name, | ||
markdown: false, | ||
type: 'text', | ||
}, | ||
}, | ||
{ | ||
type: 'row', | ||
label: 'Signer Address', | ||
value: { | ||
value: account.address, | ||
markdown: false, | ||
type: 'text', | ||
}, | ||
}, | ||
{ | ||
type: 'row', | ||
label: 'Declare Transaction Details', | ||
value: { | ||
value: toJson(request.details), | ||
markdown: false, | ||
type: 'text', | ||
}, | ||
}, | ||
]); | ||
}); | ||
|
||
it('throws `UserRejectedRequestError` if user denied the operation', async () => { | ||
const chainId = constants.StarknetChainId.SN_SEPOLIA; | ||
const account = await mockAccount(chainId); | ||
|
||
prepareMockAccount(account, state); | ||
const { confirmDialogSpy } = prepareConfirmDialog(); | ||
|
||
confirmDialogSpy.mockResolvedValue(false); | ||
|
||
const request = createRequest(chainId, account.address); | ||
|
||
await expect(signDeclareTransaction.execute(request)).rejects.toThrow( | ||
UserRejectedRequestError, | ||
); | ||
}); | ||
|
||
it('throws `InvalidParamsError` when request parameter is not correct', async () => { | ||
await expect( | ||
signDeclareTransaction.execute( | ||
{} as unknown as SignDeclareTransactionParams, | ||
), | ||
).rejects.toThrow(InvalidParamsError); | ||
}); | ||
}); |
120 changes: 120 additions & 0 deletions
120
packages/starknet-snap/src/rpcs/sign-declare-transaction.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import type { Component } from '@metamask/snaps-sdk'; | ||
import { | ||
heading, | ||
row, | ||
text, | ||
UserRejectedRequestError, | ||
} from '@metamask/snaps-sdk'; | ||
import type { DeclareSignerDetails } from 'starknet'; | ||
import type { Infer } from 'superstruct'; | ||
import { array, object, string, assign } from 'superstruct'; | ||
|
||
import { | ||
confirmDialog, | ||
AddressStruct, | ||
toJson, | ||
BaseRequestStruct, | ||
AccountRpcController, | ||
DeclareSignDetailsStruct, | ||
} from '../utils'; | ||
import { signDeclareTransaction as signDeclareTransactionUtil } from '../utils/starknetUtils'; | ||
|
||
export const SignDeclareTransactionRequestStruct = assign( | ||
object({ | ||
address: AddressStruct, | ||
details: DeclareSignDetailsStruct, | ||
}), | ||
BaseRequestStruct, | ||
); | ||
|
||
export const SignDeclareTransactionResponseStruct = array(string()); | ||
|
||
export type SignDeclareTransactionParams = Infer< | ||
typeof SignDeclareTransactionRequestStruct | ||
>; | ||
|
||
export type SignDeclareTransactionResponse = Infer< | ||
typeof SignDeclareTransactionResponseStruct | ||
>; | ||
|
||
/** | ||
* The RPC handler to sign a declare transaction. | ||
*/ | ||
export class SignDeclareTransactionRpc extends AccountRpcController< | ||
SignDeclareTransactionParams, | ||
SignDeclareTransactionResponse | ||
> { | ||
protected requestStruct = SignDeclareTransactionRequestStruct; | ||
|
||
protected responseStruct = SignDeclareTransactionResponseStruct; | ||
|
||
/** | ||
* Execute the sign declare transaction request handler. | ||
* It will show a confirmation dialog to the user before signing the declare transaction. | ||
* | ||
* @param params - The parameters of the request. | ||
* @param params.address - The address of the signer. | ||
* @param params.details - The declare transaction details to sign. | ||
* @param [params.enableAuthorize] - Optional, a flag to enable or display the confirmation dialog to the user. | ||
* @param params.chainId - The chain id of the network. | ||
* @returns the signature of the message in string array. | ||
*/ | ||
async execute( | ||
params: SignDeclareTransactionParams, | ||
): Promise<SignDeclareTransactionResponse> { | ||
return super.execute(params); | ||
} | ||
|
||
protected async handleRequest( | ||
params: SignDeclareTransactionParams, | ||
): Promise<SignDeclareTransactionResponse> { | ||
const { details } = params; | ||
if (!(await this.getSignDeclareTransactionConsensus(details))) { | ||
throw new UserRejectedRequestError() as unknown as Error; | ||
} | ||
|
||
return (await signDeclareTransactionUtil( | ||
this.account.privateKey, | ||
details as unknown as DeclareSignerDetails, | ||
)) as unknown as SignDeclareTransactionResponse; | ||
} | ||
|
||
protected async getSignDeclareTransactionConsensus( | ||
details: Infer<typeof DeclareSignDetailsStruct>, | ||
) { | ||
const components: Component[] = []; | ||
components.push(heading('Do you want to sign this transaction?')); | ||
components.push( | ||
row( | ||
'Network', | ||
text({ | ||
value: this.network.name, | ||
markdown: false, | ||
}), | ||
), | ||
); | ||
components.push( | ||
row( | ||
'Signer Address', | ||
text({ | ||
value: details.senderAddress, | ||
markdown: false, | ||
}), | ||
), | ||
); | ||
|
||
components.push( | ||
row( | ||
'Declare Transaction Details', | ||
text({ | ||
value: toJson(details), | ||
markdown: false, | ||
}), | ||
), | ||
); | ||
|
||
return await confirmDialog(components); | ||
} | ||
} | ||
|
||
export const signDeclareTransaction = new SignDeclareTransactionRpc(); |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.