feat: allow to alter signing provider for wallets - #2333
feat: allow to alter signing provider for wallets#2333mateuszpiatkowski-da wants to merge 16 commits into
Conversation
…dd `changeSigningProvider` endpoint Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
…form Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
…it wallet form Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
…allow-to-alter-signing-provider-for-wallets Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
mjuchli-da
left a comment
There was a problem hiding this comment.
You nailed it conceptually! Left a few tweaks
| { | ||
| "name": "listSigningProviderVaults", | ||
| "description": "Lists available vaults of a signing provider", | ||
| "name": "listSigningProviderKeys", |
There was a problem hiding this comment.
why does that replace listSigningProviderVaults instead of it being an addition?
There was a problem hiding this comment.
AFAIK this method returns a set of keys assigned to a signing provider. "Vaults" is a reserved keyword for Fireblocks, but it doesn't make sense to keep this naming convention when extending the functionality to other SP, hence the change in naming :)
| } | ||
| }, | ||
| { | ||
| "name": "changeSigningProvider", |
There was a problem hiding this comment.
should we use a more generalized updateWallet for this?
There was a problem hiding this comment.
I'm a little reluctant about this - updateWallet would suggest the ability to edit any/all properties of a specified wallet, whereas here we're only interested in updating the portion of the data associated with the SP. If you want I could create a generic method called like that and enable the user to update any property and use it to update the SP data where required
| '/api-keys/add', | ||
| '/api-keys', | ||
| '/login', | ||
| '/parties/edit', |
There was a problem hiding this comment.
Can be a follow-up but I suggest changing routes that involve /parties with /wallets
There was a problem hiding this comment.
Wasn't this change Wallets -> Parties in what is visible in UI a product decision?
| protected signingDriver: SigningDriverInterface | ||
| ) {} | ||
|
|
||
| private handleSigningError<T extends object>(result: SigningError | T): T { |
There was a problem hiding this comment.
The name is misleading. I initially thought it's related to signing, but it's related to a signing driver api call.
There was a problem hiding this comment.
Also the method is repetitive; perhaps something to extract to a central location
| return this.store.updateWallet(walletUpdate) | ||
| } | ||
|
|
||
| async getVaults(userId: UserId): Promise<{ vaults: string[] }> { |
There was a problem hiding this comment.
Ah I start to understand that vaults and keys are the same here.
There was a problem hiding this comment.
Thus vaults listing was redundant; correct me if i'm wrong
There was a problem hiding this comment.
Exactly, Fireblocks vaults are equal to keys. Fireblocks had it earlier, because unlike other drivers it doesn't allow creating keys, you have to select pre-existing vault when creating a party.
| protected signingDriver: SigningDriverInterface | ||
| ) {} | ||
|
|
||
| private handleSigningError<T extends object>(result: SigningError | T): T { |
| protected signingDriver: SigningDriverInterface | ||
| ) {} | ||
|
|
||
| private handleSigningError<T extends object>(result: SigningError | T): T { |
| protected signingDriver: SigningDriverInterface | ||
| ) {} | ||
|
|
||
| private handleSigningError<T extends object>(result: SigningError | T): T { |
| signingProviderId: | ||
| resolvedSigningProvider.signingProviderId, | ||
| disabled: !isMatched, | ||
| userId: '', |
There was a problem hiding this comment.
Why empty userId? You can get current user ID by this.authContext.userId, but store.addWallet doesn't need it anyway, because it also extracts userId from authContext.
| }) | ||
| } | ||
|
|
||
| async getWallet(constraint: WalletUniqueConstraint) { |
There was a problem hiding this comment.
I'm not sure about manually passing userId to store. Other methods take userId from authContext (assertConnected). User Alice shouldn't be able to get Wallet that belongs to Bob and it's good to have this constraint on store level. Unless you need to be able to get Wallet of any user from some service, I would adhere to convention that store gets userId from authContext, not from a param.
| "additionalProperties": false, | ||
| "properties": { | ||
| "userId": { | ||
| "title": "userId", |
There was a problem hiding this comment.
This allows a user to log in as user Bob to Network1 and get Wallet of user Alice for Network2. Even if UI constrains it, one could execute a request manually.
| changeSigningProvider: async ( | ||
| params: ChangeSigningProviderParams | ||
| ): Promise<null> => { | ||
| const { signingProviderId, partyId, publicKey } = params |
There was a problem hiding this comment.
I'm not sure if we should trust that request payload contains singingProviderId that exists and a publicKey that belongs to that signing provider. Perhaps we should try to do listSigningProviderKeys (or extract a subset of that method this one) and compare request params against result before changing wallet record?
| const keys = await walletAllocationService.getKeys( | ||
| assertConnected(authContext), | ||
| params.signingProviderId as SigningProvider | ||
| ) | ||
| if ( | ||
| !drivers[params.signingProviderId as SigningProvider] || | ||
| !keys | ||
| ) { |
There was a problem hiding this comment.
I would switch order - first check that driver is registered, act on it (getKeys) afterwards.
| .publicKeys=${this.publicKeys} | ||
| .selectedSigningProvider=${this.selectedSigningProvider} | ||
| .partyId=${this.walletConstraint.partyId} | ||
| .selectedPublicKeyId=${this.selectedPublicKey} |
There was a problem hiding this comment.
Does that work? Inside edit-form we compare wallet.publicKey against key.id. I assumed those are not (or not always) equal.
| ): Promise<void> { | ||
| // For dApp-triggered approvals the popup is opened with | ||
| // `closeafteraction`, so success is signalled by the popup closing. | ||
| // dApp-triggered approvals often close the popup, but newer flows can |
There was a problem hiding this comment.
I preferred previous comment.
It's not like it happens "often" or "rarely", nor there are "newer" and "older" flows. It is deterministic based on whether approve screen is triggereed via dapp-sdk, or by going to WG transaction list, you will get query param closeafteraction or not.
| .getByRole('button', { name: 'Create' }) | ||
| .click() | ||
| const submitButton = (await this.page()).getByRole('button', { | ||
| name: /^(Add|Create)$/, |
There was a problem hiding this comment.
There is more than one button text?
|
|
||
| private _onWalletEdit(e: WalletCardEditEvent) { | ||
| setLocationHref( | ||
| `/parties/edit?partyId=${e.wallet.partyId}&networkId=${e.wallet.networkId}&userId=${e.wallet.userId}` |
There was a problem hiding this comment.
Could you use toRelPath also here? It could work on with dev but fail with build without that.
| try { | ||
| await this.userClient.request({ | ||
| method: 'changeSigningProvider', | ||
| params: event, |
There was a problem hiding this comment.
I wouldn't pass DOM Event directly to API, better extract specific properties from it.
| if (network === undefined) { | ||
| throw new Error('No network session found') | ||
| } | ||
| if (!network.adminAuth) { |
There was a problem hiding this comment.
This method doesn't really need adminAuth, but I understand that we need it for PartyAllocationService constructor, even tho we only need it to create a fingerprint which doesn't require adminAuth.
I created a separate tech debt issue to address those unnecessary adminAuth dependencies #2360
| return this.securosysAllocator | ||
| case SigningProvider.WALLET_KERNEL: | ||
| return this.kernelAllocator | ||
| case SigningProvider.PARTICIPANT: |
There was a problem hiding this comment.
Now that we have BitGo driver merged, you will need to sync your branch with main and add case for it here and make sure getKeys is available in it's allocator.
…provider-for-wallets
Signed-off-by: Pawel Stepien <pawel.stepien@digitalasset.com>
Signed-off-by: Mateusz Piątkowski <mateusz.piatkowski@digitalasset.com>
.