From fb0064d0cc76cd8ea213a518ca199e92f0b35e0d Mon Sep 17 00:00:00 2001 From: Marek Polak Date: Mon, 29 Nov 2021 10:31:29 +0100 Subject: [PATCH] feat(suite): #4512 add AOPP support to reducers --- .../suite/constants/protocolConstants.ts | 2 ++ .../src/actions/suite/protocolActions.ts | 20 ++++++++++- .../src/reducers/suite/protocolReducer.ts | 22 ++++++++++++ .../src/utils/suite/__fixtures__/parseUri.ts | 36 +++++++++++++++++++ packages/suite/src/utils/suite/parseUri.ts | 27 +++++++++++++- .../suite/src/utils/wallet/accountUtils.ts | 3 ++ 6 files changed, 108 insertions(+), 2 deletions(-) diff --git a/packages/suite/src/actions/suite/constants/protocolConstants.ts b/packages/suite/src/actions/suite/constants/protocolConstants.ts index af32590d556..fa2fa35bf63 100644 --- a/packages/suite/src/actions/suite/constants/protocolConstants.ts +++ b/packages/suite/src/actions/suite/constants/protocolConstants.ts @@ -1,3 +1,5 @@ export const FILL_SEND_FORM = '@protocol/fill-send-form'; export const SAVE_COIN_PROTOCOL = '@protocol/save-coin-protocol'; +export const FILL_AOPP = '@protocol/fill-aopp'; +export const SAVE_AOPP_PROTOCOL = '@protocol/save-aopp-protocol'; export const RESET = '@protocol/reset'; diff --git a/packages/suite/src/actions/suite/protocolActions.ts b/packages/suite/src/actions/suite/protocolActions.ts index 98b12343564..b33ab30eb5b 100644 --- a/packages/suite/src/actions/suite/protocolActions.ts +++ b/packages/suite/src/actions/suite/protocolActions.ts @@ -1,15 +1,23 @@ import { PROTOCOL } from './constants'; -import { PROTOCOL_SCHEME } from '@suite-reducers/protocolReducer'; +import { AoppState, PROTOCOL_SCHEME } from '@suite-reducers/protocolReducer'; export type ProtocolAction = | { type: typeof PROTOCOL.FILL_SEND_FORM; payload: boolean; } + | { + type: typeof PROTOCOL.FILL_AOPP; + payload: boolean; + } | { type: typeof PROTOCOL.SAVE_COIN_PROTOCOL; payload: { scheme: PROTOCOL_SCHEME; address: string; amount?: number }; } + | { + type: typeof PROTOCOL.SAVE_AOPP_PROTOCOL; + payload: AoppState; + } | { type: typeof PROTOCOL.RESET }; export const fillSendForm = (shouldFillSendForm: boolean): ProtocolAction => ({ @@ -26,6 +34,16 @@ export const saveCoinProtocol = ( payload: { scheme, address, amount }, }); +export const fillAopp = (shouldFill: boolean): ProtocolAction => ({ + type: PROTOCOL.FILL_AOPP, + payload: shouldFill, +}); + +export const saveAoppProtocol = (payload: AoppState): ProtocolAction => ({ + type: PROTOCOL.SAVE_AOPP_PROTOCOL, + payload, +}); + export const resetProtocol = (): ProtocolAction => ({ type: PROTOCOL.RESET, }); diff --git a/packages/suite/src/reducers/suite/protocolReducer.ts b/packages/suite/src/reducers/suite/protocolReducer.ts index 15b69b91126..7ed077d657f 100644 --- a/packages/suite/src/reducers/suite/protocolReducer.ts +++ b/packages/suite/src/reducers/suite/protocolReducer.ts @@ -5,6 +5,7 @@ import type { Network } from '@wallet-types'; export enum PROTOCOL_SCHEME { BITCOIN = 'bitcoin', + AOPP = 'aopp', } export const PROTOCOL_TO_SYMBOL: { [key: string]: Network['symbol'] } = { @@ -18,12 +19,23 @@ export interface SendFormState { shouldFillSendForm?: boolean; } +export interface AoppState { + message: string; + asset: Network['symbol']; + callback?: string; + format?: string; +} + export interface State { sendForm: SendFormState; + aopp: Partial & { + shouldFill?: boolean; + }; } export const initialState: State = { sendForm: {}, + aopp: {}, }; const protocolReducer = (state: State = initialState, action: Action): State => @@ -38,6 +50,16 @@ const protocolReducer = (state: State = initialState, action: Action): State => draft.sendForm.amount = action.payload.amount; draft.sendForm.shouldFillSendForm = false; break; + case PROTOCOL.FILL_AOPP: + draft.aopp.shouldFill = action.payload; + break; + case PROTOCOL.SAVE_AOPP_PROTOCOL: + draft.aopp.message = action.payload.message; + draft.aopp.callback = action.payload.callback; + draft.aopp.asset = action.payload.asset; + draft.aopp.format = action.payload.format; + draft.aopp.shouldFill = false; + break; case PROTOCOL.RESET: return initialState; // no default diff --git a/packages/suite/src/utils/suite/__fixtures__/parseUri.ts b/packages/suite/src/utils/suite/__fixtures__/parseUri.ts index baff265a90e..939a5b8cc64 100644 --- a/packages/suite/src/utils/suite/__fixtures__/parseUri.ts +++ b/packages/suite/src/utils/suite/__fixtures__/parseUri.ts @@ -130,6 +130,42 @@ export const getProtocolInfo = [ amount: undefined, }, }, + { + description: 'valid AOPP uri', + uri: 'aopp:?v=0&msg=MESSAGE&asset=btc&format=any&callback=https%3A%2F%2Ftesting.21analytics.ch%2Fproofs%2Fc220a28e-0e99-4be6-8578-a886f628ee20', + result: { + scheme: 'aopp', + v: '0', + msg: 'MESSAGE', + asset: 'btc', + format: 'any', + callback: 'https://testing.21analytics.ch/proofs/c220a28e-0e99-4be6-8578-a886f628ee20', + }, + }, + { + description: 'valid AOPP uri with invalid callback', + uri: 'aopp:?v=0&msg=MESSAGE&asset=btc&format=any&callback=a', + result: { + scheme: 'aopp', + v: '0', + msg: 'MESSAGE', + asset: 'btc', + format: 'any', + callback: undefined, + }, + }, + { + description: 'valid AOPP uri, callback with slashes', + uri: 'aopp:?v=0&msg=MESSAGE&asset=btc&format=any&callback=https://foo.bar', + result: { + scheme: 'aopp', + v: '0', + msg: 'MESSAGE', + asset: 'btc', + format: 'any', + callback: 'https://foo.bar', + }, + }, { description: 'invalid uri', uri: 'gibberish', diff --git a/packages/suite/src/utils/suite/parseUri.ts b/packages/suite/src/utils/suite/parseUri.ts index d7cd95dbc38..fd31462c0aa 100644 --- a/packages/suite/src/utils/suite/parseUri.ts +++ b/packages/suite/src/utils/suite/parseUri.ts @@ -1,4 +1,6 @@ import { PROTOCOL_SCHEME } from '@suite-reducers/protocolReducer'; +import { isNetworkSymbol } from '@wallet-utils/accountUtils'; +import type { Network } from '@wallet-types'; // Parse URL query string (like 'foo=bar&baz=1337) into an object export const parseQuery = (uri: string) => { @@ -29,7 +31,16 @@ export type BitcoinProtocolInfo = { amount?: number; }; -export const getProtocolInfo = (uri: string): BitcoinProtocolInfo | null => { +export type AoppProtocolInfo = { + scheme: PROTOCOL_SCHEME.AOPP; + msg: string; + asset: Network['symbol']; + v?: string; + format?: string; + callback?: string; +}; + +export const getProtocolInfo = (uri: string): BitcoinProtocolInfo | AoppProtocolInfo | null => { const url = parseUri(uri); if (!url) return null; @@ -49,5 +60,19 @@ export const getProtocolInfo = (uri: string): BitcoinProtocolInfo | null => { }; } + if (scheme === PROTOCOL_SCHEME.AOPP) { + if (!params.msg) return null; + if (!params.asset || !isNetworkSymbol(params.asset)) return null; + const validCallback = parseUri(params.callback ?? ''); + return { + scheme, + v: params.v, + asset: params.asset, + format: params.format, + msg: params.msg, + callback: validCallback ? params.callback : undefined, + }; + } + return null; }; diff --git a/packages/suite/src/utils/wallet/accountUtils.ts b/packages/suite/src/utils/wallet/accountUtils.ts index 137c10ed49e..1b7de7b2e52 100644 --- a/packages/suite/src/utils/wallet/accountUtils.ts +++ b/packages/suite/src/utils/wallet/accountUtils.ts @@ -245,6 +245,9 @@ export const getSelectedAccount = ( export const getNetwork = (symbol: string) => NETWORKS.find(c => c.symbol === symbol) || null; +export const isNetworkSymbol = (symbol: string): symbol is Network['symbol'] => + !!getNetwork(symbol); + /** * Returns a string used as an index to separate txs for given account inside a transactions reducer *