From e6df547a2aee656a2e94209fd2cc10d6f82aa76a Mon Sep 17 00:00:00 2001 From: Alex Stelea Date: Mon, 8 May 2023 16:25:18 +0100 Subject: [PATCH] feat: add account with proof requests --- lib/IO/request-items/one-time-accounts.ts | 11 ++- lib/IO/request-items/ongoing-accounts.ts | 11 ++- lib/IO/schemas.ts | 71 +++++++++++++++----- lib/IO/transform-method-input.ts | 58 ++++++++++------ lib/__tests__/schemas.spec.ts | 8 ++- lib/__tests__/transform-method-input.spec.ts | 36 ++++++---- lib/__tests__/wallet-sdk.spec.ts | 2 + lib/methods/request.ts | 4 +- lib/wallet-sdk.ts | 2 +- 9 files changed, 140 insertions(+), 63 deletions(-) diff --git a/lib/IO/request-items/one-time-accounts.ts b/lib/IO/request-items/one-time-accounts.ts index e0ee885..8a572cd 100644 --- a/lib/IO/request-items/one-time-accounts.ts +++ b/lib/IO/request-items/one-time-accounts.ts @@ -3,15 +3,16 @@ import { Account, AccountWithProofOfOwnership, NumberOfAccountsQuantifier, - OneTimeAccountsRequestItem, + OneTimeAccountsWithoutProofOfOwnershipRequestItem, OneTimeAccountsWithoutProofOfOwnershipRequestResponseItem, + OneTimeAccountsWithProofOfOwnershipRequestItem, OneTimeAccountsWithProofOfOwnershipRequestResponseItem, } from '../schemas' export type OneTimeAccounts = { WithoutProofOfOwnership: { wallet: { - request: OneTimeAccountsRequestItem + request: OneTimeAccountsWithoutProofOfOwnershipRequestItem response: OneTimeAccountsWithoutProofOfOwnershipRequestResponseItem } method: { @@ -26,7 +27,7 @@ export type OneTimeAccounts = { } WithProofOfOwnership: { wallet: { - request: OneTimeAccountsRequestItem + request: OneTimeAccountsWithProofOfOwnershipRequestItem response: OneTimeAccountsWithProofOfOwnershipRequestResponseItem } method: { @@ -55,20 +56,24 @@ export const oneTimeAccounts = { (input: I extends NotAllowedKeys ? never : I) => ({ ...input, oneTimeAccountsWithoutProofOfOwnership: { + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', quantity, quantifier, }, }), withProofOfOwnership: ( + challenge: string, quantity = config.defaultNumberOfAccountsQuantity, quantifier = config.defaultNumberOfAccountsQuantifier ) => (input: I extends NotAllowedKeys ? never : I) => ({ ...input, oneTimeAccountsWithProofOfOwnership: { + discriminator: 'oneTimeAccountsWithProofOfOwnership', quantity, quantifier, + challenge, }, }), } diff --git a/lib/IO/request-items/ongoing-accounts.ts b/lib/IO/request-items/ongoing-accounts.ts index c9f4016..13118f3 100644 --- a/lib/IO/request-items/ongoing-accounts.ts +++ b/lib/IO/request-items/ongoing-accounts.ts @@ -3,7 +3,8 @@ import { Account, AccountWithProofOfOwnership, NumberOfAccountsQuantifier, - OngoingAccountsRequestItem, + OngoingAccountsWithProofOfOwnershipRequestItem, + OngoingAccountsWithoutProofOfOwnershipRequestItem, OngoingAccountsWithoutProofOfOwnershipRequestResponseItem, OngoingAccountsWithProofOfOwnershipRequestResponseItem, } from '../schemas' @@ -11,7 +12,7 @@ import { export type OngoingAccounts = { WithoutProofOfOwnership: { wallet: { - request: OngoingAccountsRequestItem + request: OngoingAccountsWithoutProofOfOwnershipRequestItem response: OngoingAccountsWithoutProofOfOwnershipRequestResponseItem } method: { @@ -24,7 +25,7 @@ export type OngoingAccounts = { } WithProofOfOwnership: { wallet: { - request: OngoingAccountsRequestItem + request: OngoingAccountsWithProofOfOwnershipRequestItem response: OngoingAccountsWithProofOfOwnershipRequestResponseItem } method: { @@ -56,20 +57,24 @@ export const ongoingAccounts = { (input: I extends NotAllowedKeys ? never : I) => ({ ...input, ongoingAccountsWithoutProofOfOwnership: { + discriminator: 'ongoingAccountsWithoutProofOfOwnership', quantity, quantifier, }, }), withProofOfOwnership: ( + challenge: string, quantity = config.defaultNumberOfAccountsQuantity, quantifier = config.defaultNumberOfAccountsQuantifier ) => (input: I extends NotAllowedKeys ? never : I) => ({ ...input, ongoingAccountsWithProofOfOwnership: { + discriminator: 'ongoingAccountsWithProofOfOwnership', quantity, quantifier, + challenge, }, }), } diff --git a/lib/IO/schemas.ts b/lib/IO/schemas.ts index 52b4293..cde11c7 100644 --- a/lib/IO/schemas.ts +++ b/lib/IO/schemas.ts @@ -42,6 +42,14 @@ export const PersonaDataFieldSchema = union([ literal(personaDataField.phoneNumber), ]) +const ProofSchema = object({ + publicKey: string(), + signature: string(), + curve: string(), +}) + +export type Proof = z.infer + export type PersonaDataField = z.infer const AccountSchema = object({ @@ -55,7 +63,7 @@ export type Account = z.infer const AccountWithProofOfOwnershipSchema = object({ account: AccountSchema, challenge: string(), - signature: string(), + proof: ProofSchema, }) export type AccountWithProofOfOwnership = z.infer< @@ -99,16 +107,27 @@ const MetadataSchema = object({ export type Metadata = z.infer -const OneTimeAccountsRequestItemSchema = object({ - requiresProofOfOwnership: boolean(), +const OneTimeAccountsWithoutProofOfOwnershipRequestItemSchema = object({ + discriminator: literal('oneTimeAccountsWithoutProofOfOwnership'), numberOfAccounts: NumberOfAccountsSchema, }) -export type OneTimeAccountsRequestItem = z.infer< - typeof OneTimeAccountsRequestItemSchema +export type OneTimeAccountsWithoutProofOfOwnershipRequestItem = z.infer< + typeof OneTimeAccountsWithoutProofOfOwnershipRequestItemSchema +> + +const OneTimeAccountsWithProofOfOwnershipRequestItemSchema = object({ + discriminator: literal('oneTimeAccountsWithProofOfOwnership'), + numberOfAccounts: NumberOfAccountsSchema, + challenge: string(), +}) + +export type OneTimeAccountsWithProofOfOwnershipRequestItem = z.infer< + typeof OneTimeAccountsWithProofOfOwnershipRequestItemSchema > const OneTimeAccountsWithProofOfOwnershipRequestResponseItemSchema = object({ + discriminator: literal('oneTimeAccountsWithProofOfOwnership'), accounts: AccountWithProofOfOwnershipSchema.array(), }) @@ -117,6 +136,7 @@ export type OneTimeAccountsWithProofOfOwnershipRequestResponseItem = z.infer< > const OneTimeAccountsWithoutProofOfOwnershipRequestResponseItemSchema = object({ + discriminator: literal('oneTimeAccountsWithoutProofOfOwnership'), accounts: AccountSchema.array(), }) @@ -133,16 +153,27 @@ export type OneTimeAccountsRequestResponseItem = z.infer< typeof OneTimeAccountsRequestResponseItemSchema > -const OngoingAccountsRequestItemSchema = object({ - requiresProofOfOwnership: boolean(), +const OngoingAccountsWithProofOfOwnershipRequestItemSchema = object({ + discriminator: literal('ongoingAccountsWithProofOfOwnership'), + numberOfAccounts: NumberOfAccountsSchema, + challenge: string(), +}) + +export type OngoingAccountsWithProofOfOwnershipRequestItem = z.infer< + typeof OngoingAccountsWithProofOfOwnershipRequestItemSchema +> + +const OngoingAccountsWithoutProofOfOwnershipRequestItemSchema = object({ + discriminator: literal('ongoingAccountsWithoutProofOfOwnership'), numberOfAccounts: NumberOfAccountsSchema, }) -export type OngoingAccountsRequestItem = z.infer< - typeof OngoingAccountsRequestItemSchema +export type OngoingAccountsWithoutProofOfOwnershipRequestItem = z.infer< + typeof OngoingAccountsWithoutProofOfOwnershipRequestItemSchema > const OngoingAccountsWithProofOfOwnershipRequestResponseItemSchema = object({ + discriminator: literal('ongoingAccountsWithProofOfOwnership'), accounts: AccountWithProofOfOwnershipSchema.array(), }) @@ -151,6 +182,7 @@ export type OngoingAccountsWithProofOfOwnershipRequestResponseItem = z.infer< > const OngoingAccountsWithoutProofOfOwnershipRequestResponseItemSchema = object({ + discriminator: literal('ongoingAccountsWithoutProofOfOwnership'), accounts: AccountSchema.array(), }) @@ -242,12 +274,6 @@ export type AuthLoginWithoutChallengeRequestResponseItem = z.infer< typeof AuthLoginWithoutChallengeRequestResponseItemSchema > -const ProofSchema = object({ - publicKey: string(), - signature: string(), - curve: string(), -}) - const AuthLoginWithChallengeRequestResponseItemSchema = object({ discriminator: literal('loginWithChallenge'), persona: PersonaSchema, @@ -313,7 +339,10 @@ export type SendTransactionResponseItem = z.infer< const WalletUnauthorizedRequestItemsSchema = object({ discriminator: literal('unauthorizedRequest'), - oneTimeAccounts: OneTimeAccountsRequestItemSchema.optional(), + oneTimeAccounts: union([ + OneTimeAccountsWithProofOfOwnershipRequestItemSchema, + OneTimeAccountsWithoutProofOfOwnershipRequestItemSchema, + ]).optional(), oneTimePersonaData: OneTimePersonaDataRequestItemSchema.optional(), }) @@ -324,8 +353,14 @@ export type WalletUnauthorizedRequestItems = z.infer< const WalletAuthorizedRequestItemsSchema = object({ discriminator: literal('authorizedRequest'), auth: AuthRequestItemSchema, - oneTimeAccounts: OneTimeAccountsRequestItemSchema.optional(), - ongoingAccounts: OngoingAccountsRequestItemSchema.optional(), + oneTimeAccounts: union([ + OneTimeAccountsWithProofOfOwnershipRequestItemSchema, + OneTimeAccountsWithoutProofOfOwnershipRequestItemSchema, + ]).optional(), + ongoingAccounts: union([ + OngoingAccountsWithProofOfOwnershipRequestItemSchema, + OngoingAccountsWithoutProofOfOwnershipRequestItemSchema, + ]).optional(), oneTimePersonaData: OneTimePersonaDataRequestItemSchema.optional(), ongoingPersonaData: OngoingPersonaDataRequestItemSchema.optional(), reset: ResetRequestSchema.optional(), diff --git a/lib/IO/transform-method-input.ts b/lib/IO/transform-method-input.ts index 36d2123..67abb23 100644 --- a/lib/IO/transform-method-input.ts +++ b/lib/IO/transform-method-input.ts @@ -2,6 +2,10 @@ import { ok } from 'neverthrow' import { requestMethodRequestType } from '../methods/request' import { NumberOfAccounts, + OneTimeAccountsWithProofOfOwnershipRequestItem, + OneTimeAccountsWithoutProofOfOwnershipRequestItem, + OngoingAccountsWithProofOfOwnershipRequestItem, + OngoingAccountsWithoutProofOfOwnershipRequestItem, ResetRequestItem, WalletInteractionItems, WalletUnauthorizedRequestItems, @@ -33,41 +37,55 @@ export const transformMethodInput = (input: I) => Object.entries(input).reduce( (acc, [requestType, value]: [string, any]) => { switch (requestType) { - case requestMethodRequestType.oneTimeAccountsWithoutProofOfOwnership: + case requestMethodRequestType.oneTimeAccountsWithoutProofOfOwnership: { + const oneTimeAccounts: OneTimeAccountsWithoutProofOfOwnershipRequestItem = + { + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', + numberOfAccounts: provideDefaultNumberOfAccounts(value), + } return { ...acc, - oneTimeAccounts: { - requiresProofOfOwnership: false, - numberOfAccounts: provideDefaultNumberOfAccounts(value), - }, + oneTimeAccounts, } + } - case requestMethodRequestType.oneTimeAccountsWithProofOfOwnership: + case requestMethodRequestType.oneTimeAccountsWithProofOfOwnership: { + const oneTimeAccounts: OneTimeAccountsWithProofOfOwnershipRequestItem = + { + discriminator: 'oneTimeAccountsWithProofOfOwnership', + numberOfAccounts: provideDefaultNumberOfAccounts(value), + challenge: value.challenge, + } return { ...acc, - oneTimeAccounts: { - requiresProofOfOwnership: true, - numberOfAccounts: provideDefaultNumberOfAccounts(value), - }, + oneTimeAccounts, } + } - case requestMethodRequestType.ongoingAccountsWithProofOfOwnership: + case requestMethodRequestType.ongoingAccountsWithProofOfOwnership: { + const ongoingAccounts: OngoingAccountsWithProofOfOwnershipRequestItem = + { + discriminator: 'ongoingAccountsWithProofOfOwnership', + numberOfAccounts: provideDefaultNumberOfAccounts(value), + challenge: value.challenge, + } return { ...acc, - ongoingAccounts: { - requiresProofOfOwnership: true, - numberOfAccounts: provideDefaultNumberOfAccounts(value), - }, + ongoingAccounts, } + } - case requestMethodRequestType.ongoingAccountsWithoutProofOfOwnership: + case requestMethodRequestType.ongoingAccountsWithoutProofOfOwnership: { + const ongoingAccounts: OngoingAccountsWithoutProofOfOwnershipRequestItem = + { + discriminator: 'ongoingAccountsWithoutProofOfOwnership', + numberOfAccounts: provideDefaultNumberOfAccounts(value), + } return { ...acc, - ongoingAccounts: { - requiresProofOfOwnership: false, - numberOfAccounts: provideDefaultNumberOfAccounts(value), - }, + ongoingAccounts, } + } case requestMethodRequestType.oneTimePersonaData: return { diff --git a/lib/__tests__/schemas.spec.ts b/lib/__tests__/schemas.spec.ts index d39a36c..169919d 100644 --- a/lib/__tests__/schemas.spec.ts +++ b/lib/__tests__/schemas.spec.ts @@ -11,6 +11,7 @@ import { describe('schemas', () => { it('OneTimeAccountsResponseItemSchema', () => { OneTimeAccountsRequestResponseItemSchema.parse({ + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', accounts: [ { address: 'rdx61333732663539372d383861352d3461', @@ -73,14 +74,14 @@ describe('schemas', () => { identityAddress: 'randomAddress1', }, oneTimeAccounts: { - requiresProofOfOwnership: false, + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', numberOfAccounts: { quantity: 1, quantifier: 'exactly', }, }, ongoingAccounts: { - requiresProofOfOwnership: true, + discriminator: 'ongoingAccountsWithoutProofOfOwnership', numberOfAccounts: { quantity: 5, quantifier: 'atLeast', @@ -118,6 +119,7 @@ describe('schemas', () => { items: { discriminator: 'unauthorizedRequest', oneTimeAccounts: { + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', accounts: [], }, oneTimePersonaData: { @@ -171,6 +173,7 @@ describe('schemas', () => { }, }, ongoingAccounts: { + discriminator: 'ongoingAccountsWithoutProofOfOwnership', accounts: [ { address: @@ -188,6 +191,7 @@ describe('schemas', () => { items: { discriminator: 'unauthorizedRequest', oneTimeAccounts: { + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', accounts: [ { address: diff --git a/lib/__tests__/transform-method-input.spec.ts b/lib/__tests__/transform-method-input.spec.ts index 43ca9d2..eb51a9e 100644 --- a/lib/__tests__/transform-method-input.spec.ts +++ b/lib/__tests__/transform-method-input.spec.ts @@ -13,7 +13,7 @@ describe('transformMethodInput', () => { expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.oneTimeAccounts.value]: { - requiresProofOfOwnership: false, + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', numberOfAccounts: { quantity: 1, quantifier: 'atLeast', @@ -26,7 +26,7 @@ describe('transformMethodInput', () => { expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.oneTimeAccounts.value]: { - requiresProofOfOwnership: false, + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', numberOfAccounts: { quantity: 3, quantifier: 'atLeast', @@ -35,11 +35,12 @@ describe('transformMethodInput', () => { }, }, { - actual: requestItem.oneTimeAccounts.withProofOfOwnership(), + actual: requestItem.oneTimeAccounts.withProofOfOwnership('test'), expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.oneTimeAccounts.value]: { - requiresProofOfOwnership: true, + discriminator: 'oneTimeAccountsWithProofOfOwnership', + challenge: 'test', numberOfAccounts: { quantity: 1, quantifier: 'atLeast', @@ -48,11 +49,12 @@ describe('transformMethodInput', () => { }, }, { - actual: requestItem.oneTimeAccounts.withProofOfOwnership(1), + actual: requestItem.oneTimeAccounts.withProofOfOwnership('test', 1), expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.oneTimeAccounts.value]: { - requiresProofOfOwnership: true, + discriminator: 'oneTimeAccountsWithProofOfOwnership', + challenge: 'test', numberOfAccounts: { quantity: 1, quantifier: 'atLeast', @@ -62,13 +64,15 @@ describe('transformMethodInput', () => { }, { actual: requestItem.oneTimeAccounts.withProofOfOwnership( + 'test', 5, 'exactly' ), expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.oneTimeAccounts.value]: { - requiresProofOfOwnership: true, + discriminator: 'oneTimeAccountsWithProofOfOwnership', + challenge: 'test', numberOfAccounts: { quantity: 5, quantifier: 'exactly', @@ -91,7 +95,7 @@ describe('transformMethodInput', () => { expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.ongoingAccounts.value]: { - requiresProofOfOwnership: false, + discriminator: 'ongoingAccountsWithoutProofOfOwnership', numberOfAccounts: { quantity: 1, quantifier: 'atLeast', @@ -104,7 +108,7 @@ describe('transformMethodInput', () => { expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.ongoingAccounts.value]: { - requiresProofOfOwnership: false, + discriminator: 'ongoingAccountsWithoutProofOfOwnership', numberOfAccounts: { quantity: 3, quantifier: 'atLeast', @@ -113,11 +117,12 @@ describe('transformMethodInput', () => { }, }, { - actual: requestItem.ongoingAccounts.withProofOfOwnership(), + actual: requestItem.ongoingAccounts.withProofOfOwnership('test'), expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.ongoingAccounts.value]: { - requiresProofOfOwnership: true, + discriminator: 'ongoingAccountsWithProofOfOwnership', + challenge: 'test', numberOfAccounts: { quantity: 1, quantifier: 'atLeast', @@ -126,11 +131,12 @@ describe('transformMethodInput', () => { }, }, { - actual: requestItem.ongoingAccounts.withProofOfOwnership(5), + actual: requestItem.ongoingAccounts.withProofOfOwnership('test', 5), expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.ongoingAccounts.value]: { - requiresProofOfOwnership: true, + discriminator: 'ongoingAccountsWithProofOfOwnership', + challenge: 'test', numberOfAccounts: { quantity: 5, quantifier: 'atLeast', @@ -140,13 +146,15 @@ describe('transformMethodInput', () => { }, { actual: requestItem.ongoingAccounts.withProofOfOwnership( + 'test', 10, 'exactly' ), expected: { discriminator: 'unauthorizedRequest', [RequestTypeSchema.ongoingAccounts.value]: { - requiresProofOfOwnership: true, + discriminator: 'ongoingAccountsWithProofOfOwnership', + challenge: 'test', numberOfAccounts: { quantity: 10, quantifier: 'exactly', diff --git a/lib/__tests__/wallet-sdk.spec.ts b/lib/__tests__/wallet-sdk.spec.ts index e535b81..834e28b 100644 --- a/lib/__tests__/wallet-sdk.spec.ts +++ b/lib/__tests__/wallet-sdk.spec.ts @@ -11,6 +11,7 @@ import { createLogger } from '../helpers/logger' const mockAccountWalletResponse: OneTimeAccounts['WithoutProofOfOwnership']['wallet']['response'] = { + discriminator: 'oneTimeAccountsWithoutProofOfOwnership', accounts: [ { address: 'rdx61333732663539372d383861352d3461', @@ -204,6 +205,7 @@ describe('sdk flow', () => { }, }, ongoingAccounts: { + discriminator: 'ongoingAccountsWithoutProofOfOwnership', accounts: [ { address: diff --git a/lib/methods/request.ts b/lib/methods/request.ts index 37ab9d8..d8b2365 100644 --- a/lib/methods/request.ts +++ b/lib/methods/request.ts @@ -24,9 +24,9 @@ export const requestMethodRequestType = { type RequestItems = { [requestMethodRequestType.reset]: Reset [requestMethodRequestType.oneTimeAccountsWithoutProofOfOwnership]: OneTimeAccounts['WithoutProofOfOwnership'] - // [requestMethodRequestType.oneTimeAccountsWithProofOfOwnership]: OneTimeAccounts['WithProofOfOwnership'] + [requestMethodRequestType.oneTimeAccountsWithProofOfOwnership]: OneTimeAccounts['WithProofOfOwnership'] [requestMethodRequestType.ongoingAccountsWithoutProofOfOwnership]: OngoingAccounts['WithoutProofOfOwnership'] - // [requestMethodRequestType.ongoingAccountsWithProofOfOwnership]: OngoingAccounts['WithProofOfOwnership'] + [requestMethodRequestType.ongoingAccountsWithProofOfOwnership]: OngoingAccounts['WithProofOfOwnership'] [requestMethodRequestType.usePersona]: UsePersona [requestMethodRequestType.loginWithoutChallenge]: Login['WithoutChallenge'] [requestMethodRequestType.loginWithChallenge]: Login['WithChallenge'] diff --git a/lib/wallet-sdk.ts b/lib/wallet-sdk.ts index 3d22093..c22fa72 100644 --- a/lib/wallet-sdk.ts +++ b/lib/wallet-sdk.ts @@ -49,7 +49,7 @@ export const WalletSdk = ({ } export { ManifestBuilder } from './manifest-builder' -export * from './manifest-value' +export * as ManifestValue from './manifest-value' export { requestBuilder } from './request-builder' export * from './IO/request-items' export * from './IO/schemas'