-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: revamp rpc api
starkNet_signMessage
(#312)
* chore: revamp rpc sign message * chore: updata superstruct * chore: update signMessage test * chore: refactor `showAccountRequireUpgradeOrDeployModal ` * chore: update lint style * chore: remove un used test * chore: update test folder * fix: correct typo in file path --------- Co-authored-by: Florin Dzeladini <[email protected]>
- Loading branch information
1 parent
45c127c
commit c7facfc
Showing
8 changed files
with
499 additions
and
324 deletions.
There are no files selected for viewing
35 changes: 35 additions & 0 deletions
35
packages/starknet-snap/src/__tests__/fixture/typedDataExample.json
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,35 @@ | ||
{ | ||
"types": { | ||
"StarkNetDomain": [ | ||
{ "name": "name", "type": "felt" }, | ||
{ "name": "version", "type": "felt" }, | ||
{ "name": "chainId", "type": "felt" } | ||
], | ||
"Person": [ | ||
{ "name": "name", "type": "felt" }, | ||
{ "name": "wallet", "type": "felt" } | ||
], | ||
"Mail": [ | ||
{ "name": "from", "type": "Person" }, | ||
{ "name": "to", "type": "Person" }, | ||
{ "name": "contents", "type": "felt" } | ||
] | ||
}, | ||
"primaryType": "Mail", | ||
"domain": { | ||
"name": "Starknet Mail", | ||
"version": "1", | ||
"chainId": 1 | ||
}, | ||
"message": { | ||
"from": { | ||
"name": "Cow", | ||
"wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826" | ||
}, | ||
"to": { | ||
"name": "Bob", | ||
"wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB" | ||
}, | ||
"contents": "Hello, Bob!" | ||
} | ||
} |
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 |
---|---|---|
@@ -0,0 +1,167 @@ | ||
import { | ||
InvalidParamsError, | ||
UserRejectedRequestError, | ||
} from '@metamask/snaps-sdk'; | ||
import { constants } from 'starknet'; | ||
|
||
import type { StarknetAccount } from '../test/utils'; | ||
import { generateAccounts } from '../test/utils'; | ||
import typedDataExample from './__tests__/fixture/typedDataExample.json'; | ||
import type { SignMessageParams } from './signMessage'; | ||
import { signMessage } from './signMessage'; | ||
import type { SnapState } from './types/snapState'; | ||
import { toJson } from './utils'; | ||
import { STARKNET_SEPOLIA_TESTNET_NETWORK } from './utils/constants'; | ||
import * as snapHelper from './utils/snap'; | ||
import * as snapUtils from './utils/snapUtils'; | ||
import * as starknetUtils from './utils/starknetUtils'; | ||
|
||
jest.mock('./utils/snap'); | ||
jest.mock('./utils/logger'); | ||
|
||
describe('signMessage', function () { | ||
const state: SnapState = { | ||
accContracts: [], | ||
erc20Tokens: [], | ||
networks: [STARKNET_SEPOLIA_TESTNET_NETWORK], | ||
transactions: [], | ||
}; | ||
|
||
const mockAccount = async (network: constants.StarknetChainId) => { | ||
const accounts = await generateAccounts(network, 1); | ||
return accounts[0]; | ||
}; | ||
|
||
const prepareSignMessageMock = async (account: StarknetAccount) => { | ||
const verifyIfAccountNeedUpgradeOrDeploySpy = jest.spyOn( | ||
snapUtils, | ||
'verifyIfAccountNeedUpgradeOrDeploy', | ||
); | ||
const getKeysFromAddressSpy = jest.spyOn( | ||
starknetUtils, | ||
'getKeysFromAddress', | ||
); | ||
const confirmDialogSpy = jest.spyOn(snapHelper, 'confirmDialog'); | ||
|
||
getKeysFromAddressSpy.mockResolvedValue({ | ||
privateKey: account.privateKey, | ||
publicKey: account.publicKey, | ||
addressIndex: account.addressIndex, | ||
derivationPath: account.derivationPath as unknown as any, | ||
}); | ||
|
||
verifyIfAccountNeedUpgradeOrDeploySpy.mockReturnThis(); | ||
confirmDialogSpy.mockResolvedValue(true); | ||
|
||
return { | ||
getKeysFromAddressSpy, | ||
verifyIfAccountNeedUpgradeOrDeploySpy, | ||
confirmDialogSpy, | ||
}; | ||
}; | ||
|
||
it('signs message correctly', async function () { | ||
const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA); | ||
|
||
await prepareSignMessageMock(account); | ||
|
||
const expectedResult = await starknetUtils.signMessage( | ||
account.privateKey, | ||
typedDataExample, | ||
account.address, | ||
); | ||
|
||
const request = { | ||
chainId: constants.StarknetChainId.SN_SEPOLIA, | ||
signerAddress: account.address, | ||
typedDataMessage: typedDataExample, | ||
}; | ||
const result = await signMessage(request, state); | ||
|
||
expect(result).toStrictEqual(expectedResult); | ||
}); | ||
|
||
it('renders confirmation dialog', async function () { | ||
const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA); | ||
|
||
const { confirmDialogSpy } = await prepareSignMessageMock(account); | ||
|
||
const request = { | ||
chainId: constants.StarknetChainId.SN_SEPOLIA, | ||
signerAddress: account.address, | ||
typedDataMessage: typedDataExample, | ||
enableAuthorize: true, | ||
}; | ||
|
||
await signMessage(request, state); | ||
|
||
const calls = confirmDialogSpy.mock.calls[0][0]; | ||
expect(calls).toStrictEqual([ | ||
{ type: 'heading', value: 'Do you want to sign this message?' }, | ||
{ | ||
type: 'row', | ||
label: 'Message', | ||
value: { | ||
value: toJson(typedDataExample), | ||
markdown: false, | ||
type: 'text', | ||
}, | ||
}, | ||
{ | ||
type: 'row', | ||
label: 'Signer Address', | ||
value: { | ||
value: account.address, | ||
markdown: false, | ||
type: 'text', | ||
}, | ||
}, | ||
]); | ||
}); | ||
|
||
it('throws `UserRejectedRequestError` if user denied the operation', async function () { | ||
const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA); | ||
|
||
const { confirmDialogSpy } = await prepareSignMessageMock(account); | ||
|
||
confirmDialogSpy.mockResolvedValue(false); | ||
|
||
const request = { | ||
chainId: constants.StarknetChainId.SN_SEPOLIA, | ||
signerAddress: account.address, | ||
typedDataMessage: typedDataExample, | ||
enableAuthorize: true, | ||
}; | ||
|
||
await expect(signMessage(request, state)).rejects.toThrow( | ||
UserRejectedRequestError, | ||
); | ||
}); | ||
|
||
it('throws `InvalidParamsError` when request parameter is not correct', async function () { | ||
const request = { | ||
chainId: STARKNET_SEPOLIA_TESTNET_NETWORK.chainId, | ||
}; | ||
await expect( | ||
signMessage(request as unknown as SignMessageParams, state), | ||
).rejects.toThrow(InvalidParamsError); | ||
}); | ||
|
||
it('throws `Failed to sign the message` if another error was thrown', async function () { | ||
const account = await mockAccount(constants.StarknetChainId.SN_SEPOLIA); | ||
|
||
const { getKeysFromAddressSpy } = await prepareSignMessageMock(account); | ||
|
||
getKeysFromAddressSpy.mockRejectedValue(new Error('some error')); | ||
|
||
const request = { | ||
chainId: constants.StarknetChainId.SN_SEPOLIA, | ||
signerAddress: account.address, | ||
typedDataMessage: typedDataExample, | ||
}; | ||
|
||
await expect(signMessage(request, state)).rejects.toThrow( | ||
'Failed to sign the message', | ||
); | ||
}); | ||
}); |
Oops, something went wrong.