From 38a153c01f7148c0a470c63b069f3425695b58b9 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 25 Oct 2022 20:28:57 +0530 Subject: [PATCH 01/86] abi executor base component --- .../ABI/ABIMethodExecutor/ABIMethodExecutor.scss | 7 +++++++ .../ABI/ABIMethodExecutor/ABIMethodExecutor.tsx | 13 +++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss create mode 100644 src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss new file mode 100644 index 00000000..cde5d7fd --- /dev/null +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss @@ -0,0 +1,7 @@ +@import "src/assets/colors"; + +.abi-method-executor-wrapper { + .abi-method-executor-container { + + } +} \ No newline at end of file diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx new file mode 100644 index 00000000..54eedfe7 --- /dev/null +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -0,0 +1,13 @@ +import './ABIMethodExecutor.scss'; +import React from "react"; + +function ABIMethodExecutor(): JSX.Element { + return (
+
+ + +
+
); +} + +export default ABIMethodExecutor; From 5777813a29081adea83070088054a0b986bd112f Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 25 Oct 2022 20:58:13 +0530 Subject: [PATCH 02/86] open executor modal on execute click --- .../Modules/ABI/ABIMethod/ABIMethod.scss | 3 + .../Modules/ABI/ABIMethod/ABIMethod.tsx | 21 +++++-- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 60 ++++++++++++++++++- 3 files changed, 79 insertions(+), 5 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.scss b/src/components/Modules/ABI/ABIMethod/ABIMethod.scss index e7b89d41..469e028c 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.scss +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.scss @@ -4,6 +4,9 @@ .abi-method-container { .abi-method { margin-top: 15px; + .method-exec { + margin-right: 15px; + } .method-name { font-size: 18px; font-weight: bold; diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 54cf99b9..b8df95f6 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -3,7 +3,7 @@ import React, {useState} from "react"; import { Accordion, AccordionDetails, - AccordionSummary, + AccordionSummary, Button, Chip, Grid, Tab, @@ -12,17 +12,20 @@ import { import {ExpandMore} from "@mui/icons-material"; import {ABIMethodParams, ABIMethod as ABIMethodSDK} from "algosdk"; import ABIMethodSignature from "../ABIMethodSignature/ABIMethodSignature"; +import ABIMethodExecutor from "../ABIMethodExecutor/ABIMethodExecutor"; type ABIMethodProps = { method: ABIMethodParams }; interface ABIMethodState{ - tab: string + tab: string, + showExecutor: boolean } const initialState: ABIMethodState = { - tab: "arguments" + tab: "arguments", + showExecutor: false }; function ABIMethod(props: ABIMethodProps): JSX.Element { @@ -32,7 +35,7 @@ function ABIMethod(props: ABIMethodProps): JSX.Element { const args = abiMethodInstance.args; const [ - {tab}, + {tab, showExecutor}, setState ] = useState(initialState); @@ -43,6 +46,13 @@ function ABIMethod(props: ABIMethodProps): JSX.Element { }>
+ + + {abiMethodInstance.name} @@ -106,6 +116,9 @@ function ABIMethod(props: ABIMethodProps): JSX.Element {
+ { + setState(prevState => ({...prevState, showExecutor: false})); + }}> ); } diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 54eedfe7..5f89e174 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -1,10 +1,68 @@ import './ABIMethodExecutor.scss'; import React from "react"; +import {ABIMethodParams} from "algosdk"; +import {Dialog, DialogActions, DialogContent, DialogTitle, IconButton} from "@mui/material"; +import {CancelOutlined} from "@mui/icons-material"; +import ABIMethodSignature from "../ABIMethodSignature/ABIMethodSignature"; + +interface ABIMethodExecutorProps{ + show: boolean, + method: ABIMethodParams, + handleClose?: Function +} + +const defaultProps: ABIMethodExecutorProps = { + show: false, + method: { + args: [], + name: '', + returns: { + type: '', + desc: '', + }, + desc: '' + } +}; + +function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.method, handleClose}: ABIMethodExecutorProps): JSX.Element { + + function onClose(ev) { + handleClose(); + ev.preventDefault(); + ev.stopPropagation(); + } -function ABIMethodExecutor(): JSX.Element { return (
+ {show ? + +
+
+
Execute ABI Method
+
+
+ + + +
+ +
+
+ +
+ +
+
+ + + +
: ''}
); From ebbd270fd3e99dd7742846b003851ef50f27452b Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 00:18:26 +0530 Subject: [PATCH 03/86] breif info --- .../ABI/ABIMethodExecutor/ABIMethodExecutor.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 5f89e174..37490f0d 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -1,9 +1,8 @@ import './ABIMethodExecutor.scss'; import React from "react"; -import {ABIMethodParams} from "algosdk"; -import {Dialog, DialogActions, DialogContent, DialogTitle, IconButton} from "@mui/material"; +import {ABIMethod, ABIMethodParams} from "algosdk"; +import {Alert, Dialog, DialogActions, DialogContent, DialogTitle, IconButton} from "@mui/material"; import {CancelOutlined} from "@mui/icons-material"; -import ABIMethodSignature from "../ABIMethodSignature/ABIMethodSignature"; interface ABIMethodExecutorProps{ show: boolean, @@ -32,6 +31,8 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth ev.stopPropagation(); } + const abiMethodInstance = new ABIMethod(method); + return (
@@ -56,7 +57,13 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
- + +
+ + {abiMethodInstance.getSignature()} + +
+
From c743a6ae1a8bbf757e2471ae378f3d58b52dd1a1 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 09:37:53 +0530 Subject: [PATCH 04/86] check if method can be executed and show error message --- .../Common/JsonViewer/JsonViewer.tsx | 2 +- .../KMDConfiguration/KMDConfiguration.tsx | 2 +- src/components/LeftBar/Settings/Settings.tsx | 2 +- .../ABIMethodExecutor/ABIMethodExecutor.scss | 14 +++++++ .../ABIMethodExecutor/ABIMethodExecutor.tsx | 37 +++++++++++++------ .../Modules/ABI/ImportABI/ImportABI.tsx | 2 +- .../AssetARCValidator/AssetARCValidator.tsx | 2 +- .../AppCallTxnInnerTxns.tsx | 2 +- .../Modules/Explorer/Search/Search.tsx | 2 +- src/packages/abi/classes/ABIMethodExecutor.ts | 34 +++++++++++++++++ src/packages/abi/types.ts | 6 ++- 11 files changed, 85 insertions(+), 20 deletions(-) create mode 100644 src/packages/abi/classes/ABIMethodExecutor.ts diff --git a/src/components/Common/JsonViewer/JsonViewer.tsx b/src/components/Common/JsonViewer/JsonViewer.tsx index 908d3d43..33e79b64 100644 --- a/src/components/Common/JsonViewer/JsonViewer.tsx +++ b/src/components/Common/JsonViewer/JsonViewer.tsx @@ -70,7 +70,7 @@ function JsonViewer(props): JSX.Element {
{title}
- +
diff --git a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx index 1b34d4ac..3a70775f 100644 --- a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx +++ b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx @@ -136,7 +136,7 @@ function KMDConfiguration(props): JSX.Element {
KMD Configuration
- +
diff --git a/src/components/LeftBar/Settings/Settings.tsx b/src/components/LeftBar/Settings/Settings.tsx index f45b609d..d8651817 100644 --- a/src/components/LeftBar/Settings/Settings.tsx +++ b/src/components/LeftBar/Settings/Settings.tsx @@ -176,7 +176,7 @@ function Settings(): JSX.Element {
Node Settings
- + diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss index cde5d7fd..8dcf15db 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss @@ -4,4 +4,18 @@ .abi-method-executor-container { } +} + +.abi-method-executor-modal-content { + .abi-method-executor-header { + .abi-method-name { + font-family: PoppinsBold !important; + margin-bottom: 15px; + border-bottom: 1px solid $color-grey-light; + padding-bottom: 15px; + } + } + .abi-method-executor-body { + min-height: 500px; + } } \ No newline at end of file diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 37490f0d..f6318dd8 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -1,8 +1,10 @@ import './ABIMethodExecutor.scss'; import React from "react"; import {ABIMethod, ABIMethodParams} from "algosdk"; -import {Alert, Dialog, DialogActions, DialogContent, DialogTitle, IconButton} from "@mui/material"; +import {Alert, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Typography} from "@mui/material"; import {CancelOutlined} from "@mui/icons-material"; +import ABIMethodExecutorCls from '../../../../packages/abi/classes/ABIMethodExecutor'; +import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../../../../packages/abi/types"; interface ABIMethodExecutorProps{ show: boolean, @@ -31,7 +33,8 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth ev.stopPropagation(); } - const abiMethodInstance = new ABIMethod(method); + const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); + const canExecute = abiMethodExecutorInstance.canExecute(); return (
@@ -39,7 +42,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth {show ? @@ -48,7 +51,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
Execute ABI Method
- +
@@ -56,15 +59,27 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
-
- -
- - {abiMethodInstance.getSignature()} - +
+
+
+ {new ABIMethod(method).name}
- +
+
+ {!canExecute ? '' :
+ + This method cannot be executed. Only below transaction types are allowed. +
+ + {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES.join(', ')} + +
+
+
} + +
+ diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.tsx b/src/components/Modules/ABI/ImportABI/ImportABI.tsx index 3816558b..c21ea80f 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.tsx +++ b/src/components/Modules/ABI/ImportABI/ImportABI.tsx @@ -72,7 +72,7 @@ function ImportABI(props): JSX.Element {
Import ABI
- +
diff --git a/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx b/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx index a211b0fc..58137ebc 100644 --- a/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx +++ b/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx @@ -110,7 +110,7 @@ function AssetARCValidator(props): JSX.Element {
ARC Validator
- +
diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx index 9ee7d7f7..4ea4db2b 100644 --- a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx @@ -183,7 +183,7 @@ function AppCallTxnInnerTxns(props): JSX.Element {
 
- + diff --git a/src/components/Modules/Explorer/Search/Search.tsx b/src/components/Modules/Explorer/Search/Search.tsx index 73662516..5d9928b6 100644 --- a/src/components/Modules/Explorer/Search/Search.tsx +++ b/src/components/Modules/Explorer/Search/Search.tsx @@ -185,7 +185,7 @@ function Search(): JSX.Element {
Search results
- + diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts new file mode 100644 index 00000000..2ff13e8c --- /dev/null +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -0,0 +1,34 @@ +import {ABIMethod, ABIMethodParams, abiTypeIsTransaction} from "algosdk"; +import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; + +export default class ABIMethodExecutor { + method: ABIMethodParams + + constructor(method: ABIMethodParams) { + this.method = method; + } + + canExecute(): boolean { + let args = new ABIMethod(this.method).args; + if (!args) { + args = []; + } + + let supported = true; + + args.forEach((arg) => { + const type = arg.type; + if (abiTypeIsTransaction(type)) { + if (ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES.indexOf(type) === -1) { + supported = false; + } + } + }); + + return supported; + } + + isGroup(): boolean { + return new ABIMethod(this.method).txnCount() > 1; + } +} \ No newline at end of file diff --git a/src/packages/abi/types.ts b/src/packages/abi/types.ts index be669f03..2ecf45ba 100644 --- a/src/packages/abi/types.ts +++ b/src/packages/abi/types.ts @@ -1,8 +1,10 @@ -import {ABIContractParams} from "algosdk"; +import {ABIContractParams, ABITransactionType} from "algosdk"; export interface A_Application_ABI { id?: number, network: string; app: number; abi: ABIContractParams; -} \ No newline at end of file +} + +export const ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES = [ABITransactionType.pay, ABITransactionType.axfer]; \ No newline at end of file From f5ef2f00beac50b01724dc1e4627668949eb8bb4 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 09:39:02 +0530 Subject: [PATCH 05/86] minor bugfix --- .../Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index f6318dd8..716d3ee2 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -66,7 +66,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
- {!canExecute ? '' :
+ {canExecute ? '' :
This method cannot be executed. Only below transaction types are allowed.
From e6793f8497b9b0cb2d8b12ba19661950fc0ad091 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 12:11:09 +0530 Subject: [PATCH 06/86] mehod signature inside executor modal --- .../ABIMethodExecutor/ABIMethodExecutor.scss | 8 +++- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 40 ++++++++++++---- .../ABIMethodSignature.scss | 8 +--- .../ABIMethodSignature/ABIMethodSignature.tsx | 47 +++++++++++-------- src/packages/abi/classes/ABIMethodExecutor.ts | 37 ++++++++++----- src/packages/abi/types.ts | 2 +- src/theme/index.ts | 6 +++ 7 files changed, 98 insertions(+), 50 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss index 8dcf15db..45654fba 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss @@ -16,6 +16,12 @@ } } .abi-method-executor-body { - min-height: 500px; + .abi-method-executor-panel-wrapper { + .abi-method-executor-panel-container { + min-height: 500px; + border-right: 1px solid $color-grey-light; + padding: 0 15px 0 0; + } + } } } \ No newline at end of file diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 716d3ee2..7c407505 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -1,10 +1,12 @@ import './ABIMethodExecutor.scss'; import React from "react"; import {ABIMethod, ABIMethodParams} from "algosdk"; -import {Alert, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Typography} from "@mui/material"; +import {Alert, Dialog, DialogActions, DialogContent, DialogTitle, Grid, IconButton, Typography} from "@mui/material"; import {CancelOutlined} from "@mui/icons-material"; import ABIMethodExecutorCls from '../../../../packages/abi/classes/ABIMethodExecutor'; import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../../../../packages/abi/types"; +import ABIMethodSignature from "../ABIMethodSignature/ABIMethodSignature"; +import {shadedClr} from "../../../../utils/common"; interface ABIMethodExecutorProps{ show: boolean, @@ -66,16 +68,34 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
- {canExecute ? '' :
- - This method cannot be executed. Only below transaction types are allowed. -
- - {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES.join(', ')} - + + + +
+
+ {canExecute ? '' :
+ + This method cannot be executed. Only below transaction types are supported. +
+ + Supported : {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES.join(', ')} + + + Current : {abiMethodExecutorInstance.getTxnTypes().join(', ')} + +
+
+
} +
- -
} + + + + + + + +
diff --git a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss index d3183a43..e1ba099e 100644 --- a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss +++ b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss @@ -11,15 +11,11 @@ margin-bottom: 5px; font-family: PoppinsLight !important; font-size: 14px; - &.inline { - display: inline-block; - } } .method-sig-section-value { font-weight: bold; - &.inline { - display: inline-block; - margin-left: 10px; + &.break { + word-break: break-word; } } } diff --git a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx index 74ed1e1e..d8d999c5 100644 --- a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx +++ b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx @@ -8,8 +8,13 @@ import { import {TEXT_ENCODING} from "../../../../packages/core-sdk/constants"; import {ABIMethodParams, ABIMethod} from "algosdk"; +type colorType = "warning" | "error" | "success" | "info"; + type ABIMethodProps = { - method: ABIMethodParams + method: ABIMethodParams, + sx?: any, + color?: colorType + fields?: string[] }; interface ABIMethodSignatureState{ @@ -20,9 +25,8 @@ const initialState: ABIMethodSignatureState = { textEncoding: 'hex' }; -function ABIMethodSignature(props: ABIMethodProps): JSX.Element { - - const {method} = props; +function ABIMethodSignature({method, sx = {}, fields = ['sig','count','selector'], color = "warning"} : ABIMethodProps): JSX.Element { + const abiMethodInstance = new ABIMethod(method); const [ @@ -30,6 +34,7 @@ function ABIMethodSignature(props: ABIMethodProps): JSX.Element { setState ] = useState(initialState); + console.log(fields); function setTextEncoding(encoding: string) { setState(prevState => ({...prevState, textEncoding: encoding})); } @@ -37,36 +42,38 @@ function ABIMethodSignature(props: ABIMethodProps): JSX.Element { return (
- -
+ + {fields.indexOf('sig') === -1 ? '' :
Method signature :
-
+
{abiMethodInstance.getSignature()}
-
-
-
- Txn count : -
-
- {abiMethodInstance.txnCount()} +
} + + + {fields.indexOf('count') === -1 ? '' :
+
+ Txn count : {abiMethodInstance.txnCount()}
-
- +
} + + {fields.indexOf('selector') === -1 ? '' :
Method selector : - - - + + +
{textEncoding === TEXT_ENCODING.HEX ? Buffer.from(abiMethodInstance.getSelector()).toString("hex") : ''} {textEncoding === TEXT_ENCODING.BASE64 ? Buffer.from(abiMethodInstance.getSelector()).toString("base64") : ''}
-
+ } + + diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 2ff13e8c..9bcafa43 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -1,4 +1,4 @@ -import {ABIMethod, ABIMethodParams, abiTypeIsTransaction} from "algosdk"; +import {ABIArgumentType, ABIMethod, ABIMethodParams, ABITransactionType, abiTypeIsTransaction} from "algosdk"; import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; export default class ABIMethodExecutor { @@ -8,20 +8,18 @@ export default class ABIMethodExecutor { this.method = method; } - canExecute(): boolean { - let args = new ABIMethod(this.method).args; - if (!args) { - args = []; - } + getArgs(): Array<{ type: ABIArgumentType; name?: string; description?: string }> { + return new ABIMethod(this.method).args || []; + } + canExecute(): boolean { let supported = true; - args.forEach((arg) => { - const type = arg.type; - if (abiTypeIsTransaction(type)) { - if (ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES.indexOf(type) === -1) { - supported = false; - } + const txnTypes = this.getTxnTypes(); + + txnTypes.forEach((type) => { + if (ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES.indexOf(type) === -1) { + supported = false; } }); @@ -31,4 +29,19 @@ export default class ABIMethodExecutor { isGroup(): boolean { return new ABIMethod(this.method).txnCount() > 1; } + + getTxnTypes(): ABITransactionType[] { + const txnTypes: ABITransactionType[] = []; + + if (this.isGroup()) { + const args = this.getArgs(); + for (const arg of args) { + if (abiTypeIsTransaction(arg.type)) { + txnTypes.push(arg.type) + } + } + } + + return txnTypes; + } } \ No newline at end of file diff --git a/src/packages/abi/types.ts b/src/packages/abi/types.ts index 2ecf45ba..290012ef 100644 --- a/src/packages/abi/types.ts +++ b/src/packages/abi/types.ts @@ -7,4 +7,4 @@ export interface A_Application_ABI { abi: ABIContractParams; } -export const ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES = [ABITransactionType.pay, ABITransactionType.axfer]; \ No newline at end of file +export const ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES: ABITransactionType[] = [ABITransactionType.pay, ABITransactionType.axfer]; \ No newline at end of file diff --git a/src/theme/index.ts b/src/theme/index.ts index d3f09f50..a8037175 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -63,6 +63,12 @@ export const theme = createTheme({ '&.black-button': { background: '#000' } + }, + outlined: { + '&.black-button': { + borderColor: '#000', + color: '#000' + } } } }, From c503dfab421ca981dad7d5d54d4a5a28e5acb913 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 12:27:11 +0530 Subject: [PATCH 07/86] save abi in local storage --- src/components/Modules/ABI/ABIEditor/ABIEditor.tsx | 6 ------ src/components/Modules/ABI/ABIStudio/ABIStudio.tsx | 11 ++++++++++- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 06ffae05..6573cc26 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -14,12 +14,6 @@ function ABIEditor(props): JSX.Element { if (!abi) { abi = {methods: [], name: ""}; } - if (!hideNetworks) { - hideNetworks = false; - } - else { - hideNetworks = true; - } const abiInstance = new ABIContract(abi); const networks = abiInstance.networks; diff --git a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx index 95241281..3bcc0b71 100644 --- a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx +++ b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx @@ -1,5 +1,5 @@ import './ABIStudio.scss'; -import React, {useState} from "react"; +import React, {useEffect, useState} from "react"; import ABIEditor from "../ABIEditor/ABIEditor"; import ABIActions from "../ABIActions/ABIActions"; import {ABIContractParams} from "algosdk"; @@ -17,6 +17,14 @@ const initialState: ABIStudioState = { function ABIStudio(): JSX.Element { + useEffect(() => { + const storedAbi = localStorage.getItem('abi'); + if (storedAbi) { + setState(prevState => ({...prevState, abi: JSON.parse(storedAbi), imported: true})); + } + + }, []); + const [ {imported, abi}, setState @@ -36,6 +44,7 @@ function ABIStudio(): JSX.Element {
{ setState(prevState => ({...prevState, abi, imported: true})); + localStorage.setItem('abi', JSON.stringify(abi)); }}> {imported ? : ''}
From e9782c7480d7361dbd48e1832b50d8f11d5de0c3 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 13:03:28 +0530 Subject: [PATCH 08/86] show executor driven by component property --- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 14 ++++----- .../Modules/ABI/ABIMethod/ABIMethod.scss | 6 +++- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 30 +++++++++++-------- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 6 ++++ .../Modules/ABI/ABIMethods/ABIMethods.tsx | 9 ++++-- .../Modules/ABI/ABIStudio/ABIStudio.tsx | 2 +- 6 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 6573cc26..7d6ff532 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -7,13 +7,13 @@ import ABIMethods from "../ABIMethods/ABIMethods"; import ABINetworks from "../ABINetworks/ABINetworks"; import {ABIContract, ABIContractParams} from "algosdk"; -function ABIEditor(props): JSX.Element { - let abi: ABIContractParams = props.abi; - let hideNetworks: boolean = props.hideNetworks; +type ABIEditorProps = { + abi: ABIContractParams, + hideNetworks?: boolean, + supportExecutor?: boolean +}; - if (!abi) { - abi = {methods: [], name: ""}; - } +function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false}: ABIEditorProps): JSX.Element { const abiInstance = new ABIContract(abi); const networks = abiInstance.networks; @@ -37,7 +37,7 @@ function ABIEditor(props): JSX.Element {
{!hideNetworks ? : ''} - +
diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.scss b/src/components/Modules/ABI/ABIMethod/ABIMethod.scss index 469e028c..6b7b1645 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.scss +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.scss @@ -5,11 +5,15 @@ .abi-method { margin-top: 15px; .method-exec { - margin-right: 15px; + margin-right: 25px; + float: right; } .method-name { font-size: 18px; font-weight: bold; + margin-top: 5px; + display: inline-block; + margin-bottom: 5px; } .method-desc { margin-left: 15px; diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index b8df95f6..15078374 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -13,14 +13,16 @@ import {ExpandMore} from "@mui/icons-material"; import {ABIMethodParams, ABIMethod as ABIMethodSDK} from "algosdk"; import ABIMethodSignature from "../ABIMethodSignature/ABIMethodSignature"; import ABIMethodExecutor from "../ABIMethodExecutor/ABIMethodExecutor"; +import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; type ABIMethodProps = { - method: ABIMethodParams + method: ABIMethodParams, + supportExecutor?: boolean }; interface ABIMethodState{ tab: string, - showExecutor: boolean + showExecutor: boolean, } const initialState: ABIMethodState = { @@ -28,9 +30,9 @@ const initialState: ABIMethodState = { showExecutor: false }; -function ABIMethod(props: ABIMethodProps): JSX.Element { +function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Element { - const {method} = props; + const abiMethodInstance = new ABIMethodSDK(method); const args = abiMethodInstance.args; @@ -45,20 +47,24 @@ function ABIMethod(props: ABIMethodProps): JSX.Element { }> -
- - - +
{abiMethodInstance.name} {abiMethodInstance.description} + {supportExecutor ? + + : ''} +
diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 7c407505..8c267c64 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -46,6 +46,12 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth fullWidth={true} maxWidth={"lg"} open={show} + + PaperProps={{ + sx: { + height: '80vh' + } + }} >
diff --git a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx index 380a222a..2a78d090 100644 --- a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx +++ b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx @@ -5,9 +5,12 @@ import ABIMethod from "../ABIMethod/ABIMethod"; import {ABIContract, ABIContractParams} from "algosdk"; import {theme} from "../../../../theme"; +type ABIMethodsProps = { + abi: ABIContractParams, + supportExecutor?: boolean +}; -function ABIMethods(props): JSX.Element { - let abi: ABIContractParams = props.abi; +function ABIMethods({abi, supportExecutor = false}: ABIMethodsProps): JSX.Element { const abiInstance = new ABIContract(abi); @@ -21,7 +24,7 @@ function ABIMethods(props): JSX.Element {
{abiInstance.methods.map((method, index) => { return
- +
; })}
diff --git a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx index 3bcc0b71..7d0b6953 100644 --- a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx +++ b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx @@ -46,7 +46,7 @@ function ABIStudio(): JSX.Element { setState(prevState => ({...prevState, abi, imported: true})); localStorage.setItem('abi', JSON.stringify(abi)); }}> - {imported ? : ''} + {imported ? : ''}
From 8d0f45f5fb040a648b9db8d2805b45dbec99a04a Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 13:47:45 +0530 Subject: [PATCH 09/86] remove console logs --- .../Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx | 1 - src/packages/core-sdk/classes/core/CoreNode.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx index d8d999c5..e3e29f80 100644 --- a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx +++ b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.tsx @@ -34,7 +34,6 @@ function ABIMethodSignature({method, sx = {}, fields = ['sig','count','selector' setState ] = useState(initialState); - console.log(fields); function setTextEncoding(encoding: string) { setState(prevState => ({...prevState, textEncoding: encoding})); } diff --git a/src/packages/core-sdk/classes/core/CoreNode.ts b/src/packages/core-sdk/classes/core/CoreNode.ts index c341c410..c4a8b088 100644 --- a/src/packages/core-sdk/classes/core/CoreNode.ts +++ b/src/packages/core-sdk/classes/core/CoreNode.ts @@ -57,7 +57,6 @@ export class CoreNode { } getConsensusVersion(): string { - console.log(this.status); return this.status["last-version"]; } From ae6808c05d01d3af9f9568936031d38d964a0eae Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 17:29:19 +0530 Subject: [PATCH 10/86] ABI method definition styling --- .../Modules/ABI/ABIMethod/ABIMethod.scss | 46 ++++++- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 112 ++++++++++-------- .../Modules/Explorer/Records/Block/Block.scss | 2 +- .../Modules/Explorer/Records/Block/Block.tsx | 2 +- .../Modules/Explorer/Records/Group/Group.scss | 2 +- .../Modules/Explorer/Records/Group/Group.tsx | 2 +- .../TransactionBuilder.scss | 7 ++ .../TransactionBuilder/TransactionBuilder.tsx | 17 +++ 8 files changed, 131 insertions(+), 59 deletions(-) create mode 100644 src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss create mode 100644 src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.scss b/src/components/Modules/ABI/ABIMethod/ABIMethod.scss index 6b7b1645..f3635642 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.scss +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.scss @@ -22,6 +22,14 @@ } .method-body { margin-bottom: 15px; + .method-title { + font-weight: bold; + margin: 15px 10px; + padding-bottom: 10px; + border-bottom: 1px solid $color-grey-light; + font-family: PoppinsBold !important; + font-size: 14px; + } .method-signature { .method-sig-section { margin-bottom: 10px; @@ -45,9 +53,28 @@ } } .method-returns { - margin-top: 15px; + margin-top: 0; padding-top: 15px; - border-top: 1px solid $color-grey-light; + .method-returns-title { + font-weight: bold; + margin: 15px 10px; + padding-bottom: 10px; + border-bottom: 1px solid $color-grey-light; + font-family: PoppinsBold !important; + font-size: 14px; + } + .mini-alert { + padding: 5px 10px; + border-radius: 4px; + display: inline-block; + margin: 5px 5px 0 10px; + font-weight: bold; + text-align: center; + font-size: 13px; + .MuiAlert-message { + padding: 0; + } + } .method-returns-desc { margin-left: 10px; font-size: 14px; @@ -61,17 +88,28 @@ } .arguments { + .arguments-title { + font-weight: bold; + margin: 20px 10px; + padding-bottom: 10px; + border-bottom: 1px solid $color-grey-light; + font-family: PoppinsBold !important; + font-size: 14px; + } .arguments-header { padding: 15px; - background: $color-grey-light; + background: $color-grey-very-light; font-weight: bold; + border-bottom: 1px solid $color-grey-light; + border-top: 1px solid $color-grey-light; } .arg { padding: 15px; + border-bottom: 1px solid $color-grey-light; .arg-prop { font-size: 14px; } - &:nth-child(odd) { + &:hover { background: $color-grey-very-light; } } diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 15078374..7bb15671 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -4,16 +4,14 @@ import { Accordion, AccordionDetails, AccordionSummary, Button, - Chip, - Grid, - Tab, - Tabs + Grid } from "@mui/material"; import {ExpandMore} from "@mui/icons-material"; import {ABIMethodParams, ABIMethod as ABIMethodSDK} from "algosdk"; import ABIMethodSignature from "../ABIMethodSignature/ABIMethodSignature"; import ABIMethodExecutor from "../ABIMethodExecutor/ABIMethodExecutor"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; +import {Alert} from "@mui/lab"; type ABIMethodProps = { method: ABIMethodParams, @@ -21,12 +19,10 @@ type ABIMethodProps = { }; interface ABIMethodState{ - tab: string, showExecutor: boolean, } const initialState: ABIMethodState = { - tab: "arguments", showExecutor: false }; @@ -37,7 +33,7 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen const args = abiMethodInstance.args; const [ - {tab, showExecutor}, + {showExecutor}, setState ] = useState(initialState); @@ -70,53 +66,67 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen
- - }} value={tab} className="method-tabs" onChange={(_, newVal) => { - setState(prevState => ({...prevState, tab: newVal})); - }}> - - - -
-
- - - Name - - - Type - - - Description - - -
- - - {args.map((arg) => { - return
- - -
{arg.name}
-
- -
{arg.type.toString()}
-
- -
{arg.description}
+ + + +
Method details
+ +
+ +
+ + + +
+
Arguments
+
+ + + Name + + + Type + + + Description + - -
; - })} - -
- -
- {abiMethodInstance.returns.description} +
+ + + {args.map((arg) => { + return
+ + +
{arg.name}
+
+ +
{arg.type.toString()}
+
+ +
{arg.description}
+
+
+
; + })} + +
+
Returns
+ + {abiMethodInstance.returns.type.toString()} + + +
+ {abiMethodInstance.returns.description} +
+
+
-
+
+
+ + -
diff --git a/src/components/Modules/Explorer/Records/Block/Block.scss b/src/components/Modules/Explorer/Records/Block/Block.scss index c4815104..f2e63b1f 100644 --- a/src/components/Modules/Explorer/Records/Block/Block.scss +++ b/src/components/Modules/Explorer/Records/Block/Block.scss @@ -34,7 +34,7 @@ } .mini-alert { padding: 5px 10px; - border-radius: 25px; + border-radius: 4px; display: inline-block; margin: 5px 5px 0 0; font-weight: bold; diff --git a/src/components/Modules/Explorer/Records/Block/Block.tsx b/src/components/Modules/Explorer/Records/Block/Block.tsx index ca5f3c6b..7ff8e211 100644 --- a/src/components/Modules/Explorer/Records/Block/Block.tsx +++ b/src/components/Modules/Explorer/Records/Block/Block.tsx @@ -62,7 +62,7 @@ function Block(): JSX.Element {
{blockInstance.getTransactionsCount() > 0 ?
{txnTypesList.map((type) => { - return + return {type} })} diff --git a/src/components/Modules/Explorer/Records/Group/Group.scss b/src/components/Modules/Explorer/Records/Group/Group.scss index f1d3e115..1f05d4f4 100644 --- a/src/components/Modules/Explorer/Records/Group/Group.scss +++ b/src/components/Modules/Explorer/Records/Group/Group.scss @@ -25,7 +25,7 @@ font-family: PoppinsBold !important; .mini-alert { padding: 5px 10px; - border-radius: 25px; + border-radius: 4px; display: inline-block; margin: 5px 5px 0 0; font-weight: bold; diff --git a/src/components/Modules/Explorer/Records/Group/Group.tsx b/src/components/Modules/Explorer/Records/Group/Group.tsx index 6755b684..10d5f810 100644 --- a/src/components/Modules/Explorer/Records/Group/Group.tsx +++ b/src/components/Modules/Explorer/Records/Group/Group.tsx @@ -81,7 +81,7 @@ function Group(): JSX.Element { Total transactions : {groupInstance.getTransactionsCount()}
{txnTypesList.map((type) => { - return + return {type} })} diff --git a/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss b/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss new file mode 100644 index 00000000..cd334181 --- /dev/null +++ b/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss @@ -0,0 +1,7 @@ +@import "src/assets/colors"; + +.transaction-builder-wrapper { + .transaction-builder-container { + + } +} \ No newline at end of file diff --git a/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx b/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx new file mode 100644 index 00000000..6c953105 --- /dev/null +++ b/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx @@ -0,0 +1,17 @@ +import './TransactionBuilder.scss'; +import React, {} from "react"; + +type TransactionBuilderProps = { + +}; + +function TransactionBuilder({}: TransactionBuilderProps): JSX.Element { + + return (
+
+ +
+
); +} + +export default TransactionBuilder; From 32a599979c07ace54a9023e37f5b0f35acded376 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 26 Oct 2022 23:58:52 +0530 Subject: [PATCH 11/86] typo --- src/components/Modules/Explorer/Lists/Accounts/Accounts.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Modules/Explorer/Lists/Accounts/Accounts.tsx b/src/components/Modules/Explorer/Lists/Accounts/Accounts.tsx index a0dc4720..f67de389 100644 --- a/src/components/Modules/Explorer/Lists/Accounts/Accounts.tsx +++ b/src/components/Modules/Explorer/Lists/Accounts/Accounts.tsx @@ -93,7 +93,7 @@ function Accounts(): JSX.Element { { ...dataGridCellConfig, field: 'status', - headerName: 'Staus' + headerName: 'Status' }, { ...dataGridCellConfig, From f854a79cc329edd13cfc98d962bdc68609d866b5 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 27 Oct 2022 00:01:35 +0530 Subject: [PATCH 12/86] DAO ABI example in ABI Studio --- src/components/Modules/ABI/ImportABI/ImportABI.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.tsx b/src/components/Modules/ABI/ImportABI/ImportABI.tsx index c21ea80f..423fec18 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.tsx +++ b/src/components/Modules/ABI/ImportABI/ImportABI.tsx @@ -156,7 +156,13 @@ function ImportABI(props): JSX.Element { { setState(prevState => ({...prevState, url: "https://raw.githubusercontent.com/algorand-devrel/coin-flipper/master/contracts/artifacts/contract.json"})); - }} label="Coin Flipper" size="small" color={"warning"} variant={"outlined"} + }} label="Coin Flipper ABI" size="small" color={"warning"} variant={"outlined"} + sx={{marginLeft: '10px'}} + > + + { + setState(prevState => ({...prevState, url: "https://raw.githubusercontent.com/algorand-devrel/ExtendableDAO/main/src/contracts/dao_abi.json"})); + }} label="DAO ABI" size="small" color={"warning"} variant={"outlined"} sx={{marginLeft: '10px'}} >
From 1bb961ae384ec4c5587e2b3684ef93ba893c44ea Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 27 Oct 2022 00:18:08 +0530 Subject: [PATCH 13/86] make URL import as defaulr while ABI import --- .../Modules/ABI/ImportABI/ImportABI.scss | 4 ++-- .../Modules/ABI/ImportABI/ImportABI.tsx | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.scss b/src/components/Modules/ABI/ImportABI/ImportABI.scss index 3f3adb8e..f7139320 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.scss +++ b/src/components/Modules/ABI/ImportABI/ImportABI.scss @@ -26,9 +26,9 @@ } } } - .link-wrapper { + .url-wrapper { height: inherit; - .link-container { + .url-container { height: inherit; margin-top: 40px; } diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.tsx b/src/components/Modules/ABI/ImportABI/ImportABI.tsx index 423fec18..9c21424c 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.tsx +++ b/src/components/Modules/ABI/ImportABI/ImportABI.tsx @@ -36,7 +36,7 @@ interface ImportABIState{ } const initialState: ImportABIState = { - tab: "file", + tab: "url", url: '' }; @@ -83,12 +83,12 @@ function ImportABI(props): JSX.Element {
}}> + { + setState(prevState => ({...prevState, tab: "url"})); + }}/> { setState(prevState => ({...prevState, tab: "file"})); }}/> - { - setState(prevState => ({...prevState, tab: "link"})); - }}/>
@@ -136,18 +136,20 @@ function ImportABI(props): JSX.Element {
: ''} - {tab === 'link' ?
-
+ {tab === 'url' ?
+
Enter a URL { setState(prevState => ({...prevState, url: ev.target.value})); }} fullWidth/> -
+
Example:   { setState(prevState => ({...prevState, url: "https://raw.githubusercontent.com/algorandlabs/smart-asa/develop/smart_asa_abi.json"})); From b78aaac6fffb0140cc268cbff9be9a7dfee5b0ea Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 27 Oct 2022 00:41:05 +0530 Subject: [PATCH 14/86] UI enhancements --- src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx | 4 +++- src/components/LeftBar/Settings/Settings.tsx | 4 +++- src/components/Modules/ABI/ImportABI/ImportABI.tsx | 1 + src/components/Modules/Dispenser/Dispenser.tsx | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx index 3a70775f..5e227696 100644 --- a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx +++ b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx @@ -191,13 +191,15 @@ function KMDConfiguration(props): JSX.Element { size={"large"} color={"primary"} onClick={handleClose} - >Cancel + className="black-button" + >Close + className="black-button" + >Close +
+
+
:
+ + Group transactions are not yet supported by dappflow. It is on our roadmap though.
}
- - - + +
+
+
+ Result +
+
+
diff --git a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss index e1ba099e..d5035b62 100644 --- a/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss +++ b/src/components/Modules/ABI/ABIMethodSignature/ABIMethodSignature.scss @@ -7,6 +7,10 @@ margin-bottom: 10px; padding-bottom: 10px; border-bottom: 1px solid $color-light; + &:last-child { + border-bottom: none; + padding-bottom: 0; + } .method-sig-section-key { margin-bottom: 5px; font-family: PoppinsLight !important; diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 9bcafa43..eca76428 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -13,6 +13,10 @@ export default class ABIMethodExecutor { } canExecute(): boolean { + if (this.isGroup()) { + return false + } + let supported = true; const txnTypes = this.getTxnTypes(); @@ -44,4 +48,5 @@ export default class ABIMethodExecutor { return txnTypes; } + } \ No newline at end of file From 0b1dc4ef869eae467d5eb67bc0f2a9d88a028611 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Fri, 28 Oct 2022 19:08:43 +0530 Subject: [PATCH 17/86] move canExecute check to method component --- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 15 ++++- .../ABIMethodExecutor/ABIMethodExecutor.scss | 16 ++--- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 60 +++++++++++-------- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 7bb15671..3aa24864 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -9,9 +9,12 @@ import { import {ExpandMore} from "@mui/icons-material"; import {ABIMethodParams, ABIMethod as ABIMethodSDK} from "algosdk"; import ABIMethodSignature from "../ABIMethodSignature/ABIMethodSignature"; +import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; import ABIMethodExecutor from "../ABIMethodExecutor/ABIMethodExecutor"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {Alert} from "@mui/lab"; +import {showSnack} from "../../../../redux/common/actions/snackbar"; +import {useDispatch} from "react-redux"; type ABIMethodProps = { method: ABIMethodParams, @@ -28,7 +31,7 @@ const initialState: ABIMethodState = { function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Element { - + const dispatch = useDispatch(); const abiMethodInstance = new ABIMethodSDK(method); const args = abiMethodInstance.args; @@ -52,9 +55,17 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen {supportExecutor ?
-
:
- - Group transactions are not yet supported by dappflow. It is on our roadmap though. - -
} +
+
From a0af36e68b1cf00835f7b791de3caebddb219d1a Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Fri, 28 Oct 2022 20:48:24 +0530 Subject: [PATCH 18/86] snackbar enhancements --- src/components/App/AppSnackbar.tsx | 29 ++++++++++++------- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 2 +- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/components/App/AppSnackbar.tsx b/src/components/App/AppSnackbar.tsx index 0012f77c..46a1b008 100644 --- a/src/components/App/AppSnackbar.tsx +++ b/src/components/App/AppSnackbar.tsx @@ -2,6 +2,7 @@ import {useDispatch, useSelector} from "react-redux"; import {RootState} from "../../redux/store"; import {hideSnack} from '../../redux/common/actions/snackbar'; import {Alert, Snackbar} from "@mui/material"; +import {theme} from "../../theme"; function AppSnackbar(): JSX.Element { @@ -10,18 +11,26 @@ function AppSnackbar(): JSX.Element { // @ts-ignore return ( {dispatch(hideSnack())}}> - {dispatch(hideSnack())}}> - - + horizontal: 'right' }} + onClose={() => {dispatch(hideSnack())}}> + {dispatch(hideSnack())}}> + + ); } diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 3aa24864..1722bbe6 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -61,7 +61,7 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen if (!new ABIMethodExecutorCls(method).canExecute()) { dispatch(showSnack({ severity: 'error', - message: 'Group transactions are yet supported by dappflow. It is on our roadmap.' + message: 'Group transactions are not yet supported by Dappflow. It is on our roadmap.' })); return; } From 8f8ec0820ebeebd2ea9b396749e8c73a0a455c23 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 29 Oct 2022 16:47:27 +0530 Subject: [PATCH 19/86] save ABI executor config in local storage --- src/components/Common/Loader/Loader.tsx | 2 +- .../Modules/ABI/ABIConfig/ABIConfig.scss | 13 ++ .../Modules/ABI/ABIConfig/ABIConfig.tsx | 173 ++++++++++++++++++ .../Modules/ABI/ABIEditor/ABIEditor.tsx | 32 +++- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 8 - 5 files changed, 216 insertions(+), 12 deletions(-) create mode 100644 src/components/Modules/ABI/ABIConfig/ABIConfig.scss create mode 100644 src/components/Modules/ABI/ABIConfig/ABIConfig.tsx diff --git a/src/components/Common/Loader/Loader.tsx b/src/components/Common/Loader/Loader.tsx index de96fe91..f8f71a12 100644 --- a/src/components/Common/Loader/Loader.tsx +++ b/src/components/Common/Loader/Loader.tsx @@ -10,7 +10,7 @@ function Loader(): JSX.Element {
{loader.count ?
- +
{loader.message}
diff --git a/src/components/Modules/ABI/ABIConfig/ABIConfig.scss b/src/components/Modules/ABI/ABIConfig/ABIConfig.scss new file mode 100644 index 00000000..3bc2f529 --- /dev/null +++ b/src/components/Modules/ABI/ABIConfig/ABIConfig.scss @@ -0,0 +1,13 @@ +@import "src/assets/colors"; + +.abi-config-content { + .abi-config-content-header { + + } +} + +.abi-config-wrapper { + .abi-config-container { + + } +} \ No newline at end of file diff --git a/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx new file mode 100644 index 00000000..f2d33f71 --- /dev/null +++ b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx @@ -0,0 +1,173 @@ +import './ABIConfig.scss'; +import React, {Fragment, useEffect, useState} from "react"; +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, FormLabel, + IconButton, + InputBase, + InputBaseProps, + styled +} from "@mui/material"; +import {CancelOutlined} from "@mui/icons-material"; +import {theme} from "../../../../theme"; +import {useDispatch} from "react-redux"; +import {showSnack} from "../../../../redux/common/actions/snackbar"; +import {isNumber} from "../../../../utils/common"; +import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicationClient"; +import dappflow from "../../../../utils/dappflow"; +import {handleException} from "../../../../redux/common/actions/exception"; +import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; + + +const ShadedInput = styled(InputBase)(({ theme }) => { + return { + padding: 5, + paddingLeft: 10, + marginTop: 5, + fontSize: 14, + border: '1px solid ' + theme.palette.grey[200] + }; +}); + + +interface ABIConfigProps{ + show: boolean, + handleClose?: Function +} + +const defaultProps: ABIConfigProps = { + show: false +}; + +interface ABIConfigState{ + appId: string +} + +const initialState: ABIConfigState = { + appId: '' +}; + + +function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX.Element { + + const dispatch = useDispatch(); + + const [ + {appId}, + setState + ] = useState({ + ...initialState + }); + + useEffect(() => { + const savedAppId = localStorage.getItem('abi_app_id'); + setState(prevState => ({...prevState, appId: savedAppId})); + }, [show]); + + function onClose(ev) { + handleClose(); + ev.preventDefault(); + ev.stopPropagation(); + } + + return (
+
+ + {show ? + +
+
+
ABI Config
+
+
+ + + +
+ +
+
+ + +
+
+
+ App ID + { + setState(prevState => ({...prevState, appId: ev.target.value})); + } + } + fullWidth/> + + +
+
+ + +
+
+ +
+ + + +
: ''} + + +
+
); +} + +export default ABIConfig; diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 7d6ff532..54e29a91 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -1,11 +1,13 @@ import './ABIEditor.scss'; -import React, {} from "react"; +import React, {useState} from "react"; import {shadedClr, shadedClr2} from "../../../../utils/common"; import JsonViewer from "../../../Common/JsonViewer/JsonViewer"; -import {Box} from "@mui/material"; +import {Box, Button} from "@mui/material"; import ABIMethods from "../ABIMethods/ABIMethods"; import ABINetworks from "../ABINetworks/ABINetworks"; import {ABIContract, ABIContractParams} from "algosdk"; +import ABIConfig from "../ABIConfig/ABIConfig"; +import SettingsIcon from '@mui/icons-material/Settings'; type ABIEditorProps = { abi: ABIContractParams, @@ -13,11 +15,24 @@ type ABIEditorProps = { supportExecutor?: boolean }; +interface ABIEditorState{ + showConfig: boolean, +} + +const initialState: ABIEditorState = { + showConfig: false +}; + function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false}: ABIEditorProps): JSX.Element { const abiInstance = new ABIContract(abi); const networks = abiInstance.networks; + const [ + {showConfig}, + setState + ] = useState(initialState); + return (
@@ -31,8 +46,19 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support Description: {abiInstance.description ? abiInstance.description : '--Empty--'}
-
+
+ {supportExecutor ?
+ + {setState(prevState => ({...prevState, showConfig: false}));}}> +
: ''}
diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 311a04b9..9ebbe707 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -109,14 +109,6 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth }} fullWidth/> - - {/**/}
})}
From 60c142f48cdc82f5c75defe4c9514411c397f934 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 30 Oct 2022 00:35:57 +0530 Subject: [PATCH 20/86] check for app id before method execution modal --- .../Modules/ABI/ABIConfig/ABIConfig.tsx | 49 ++++++++++--------- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 12 +++++ .../Modules/ABI/ABIMethods/ABIMethods.scss | 9 ++++ .../Modules/ABI/ABIMethods/ABIMethods.tsx | 15 +++++- .../Modules/Dispenser/Dispenser.tsx | 5 +- src/packages/abi/classes/ABIConfig.ts | 10 ++++ 6 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 src/packages/abi/classes/ABIConfig.ts diff --git a/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx index f2d33f71..2c0a2175 100644 --- a/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx +++ b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx @@ -20,6 +20,7 @@ import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicati import dappflow from "../../../../utils/dappflow"; import {handleException} from "../../../../redux/common/actions/exception"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; +import ABIConfigCls from '../../../../packages/abi/classes/ABIConfig'; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -63,7 +64,7 @@ function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX }); useEffect(() => { - const savedAppId = localStorage.getItem('abi_app_id'); + const savedAppId = new ABIConfigCls().getAppId(); setState(prevState => ({...prevState, appId: savedAppId})); }, [show]); @@ -117,36 +118,36 @@ function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX variant={"contained"} className="black-button" onClick={async (ev) => { - if (!appId) { - dispatch(showSnack({ - severity: 'error', - message: 'Invalid App ID' - })); - return; - } - if (!isNumber(appId)) { - dispatch(showSnack({ - severity: 'error', - message: 'Invalid App ID' - })); - return; - } - try { - dispatch(showLoader('Validating App ID')); - await new ApplicationClient(dappflow.network).get(Number(appId)); - dispatch(hideLoader()); - } catch (e: any) { - dispatch(handleException(e)); - dispatch(hideLoader()); - return; + + if (appId) { + if (!isNumber(appId)) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid App ID' + })); + return; + } + + try { + dispatch(showLoader('Validating App ID')); + await new ApplicationClient(dappflow.network).get(Number(appId)); + dispatch(hideLoader()); + } catch (e: any) { + dispatch(handleException(e)); + dispatch(hideLoader()); + return; + } } - localStorage.setItem('abi_app_id', appId); + + new ABIConfigCls().setAppId(appId || ""); + dispatch(showSnack({ severity: 'success', message: 'Saved successfully.' })); + onClose(ev); } diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 1722bbe6..d6a624a1 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -15,6 +15,7 @@ import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {Alert} from "@mui/lab"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {useDispatch} from "react-redux"; +import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; type ABIMethodProps = { method: ABIMethodParams, @@ -65,6 +66,17 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen })); return; } + + const appId = new ABIConfig().getAppId(); + + if (!appId) { + dispatch(showSnack({ + severity: 'error', + message: 'App ID is null. Before you execute please setup an App ID using the config button above.' + })); + return; + } + setState(prevState => ({...prevState, showExecutor: true})); }} color={"primary"} startIcon={} diff --git a/src/components/Modules/ABI/ABIMethods/ABIMethods.scss b/src/components/Modules/ABI/ABIMethods/ABIMethods.scss index 9cd6a92d..52e9671b 100644 --- a/src/components/Modules/ABI/ABIMethods/ABIMethods.scss +++ b/src/components/Modules/ABI/ABIMethods/ABIMethods.scss @@ -4,6 +4,15 @@ .abi-methods-container { margin-top: 15px; .abi-methods-header { + display: flex; + justify-content: space-between; + .app-id { + font-size: 14px; + font-weight: bold; + margin-right: 10px; + margin-top: 10px; + color: $color-grey-dark; + } svg { vertical-align: text-bottom; margin-right: 5px; diff --git a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx index 2a78d090..8a915416 100644 --- a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx +++ b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx @@ -4,6 +4,8 @@ import IntegrationInstructionsOutlinedIcon from "@mui/icons-material/Integration import ABIMethod from "../ABIMethod/ABIMethod"; import {ABIContract, ABIContractParams} from "algosdk"; import {theme} from "../../../../theme"; +import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; +import LinkToApplication from "../../Explorer/Common/Links/LinkToApplication"; type ABIMethodsProps = { abi: ABIContractParams, @@ -13,13 +15,22 @@ type ABIMethodsProps = { function ABIMethods({abi, supportExecutor = false}: ABIMethodsProps): JSX.Element { const abiInstance = new ABIContract(abi); + const appId = new ABIConfig().getAppId(); return (
- - Methods + +
+ + Methods +
+
+ + App ID : {appId ? : 'null'} +
+
{abiInstance.methods.map((method, index) => { diff --git a/src/components/Modules/Dispenser/Dispenser.tsx b/src/components/Modules/Dispenser/Dispenser.tsx index bfec0304..5d7ab9c7 100644 --- a/src/components/Modules/Dispenser/Dispenser.tsx +++ b/src/components/Modules/Dispenser/Dispenser.tsx @@ -16,6 +16,7 @@ import KMDConfiguration from "../../LeftBar/KMDConfiguration/KMDConfiguration"; import {getKMDConfig} from "../../../utils/nodeConfig"; import {KMDConnectionParams} from "../../../packages/core-sdk/types"; import LaunchIcon from '@mui/icons-material/Launch'; +import AlgoIcon from "../Explorer/AlgoIcon/AlgoIcon"; interface DispenserState{ @@ -170,7 +171,7 @@ function Dispenser(): JSX.Element {
- Algos + }} /> diff --git a/src/packages/abi/classes/ABIConfig.ts b/src/packages/abi/classes/ABIConfig.ts new file mode 100644 index 00000000..b598640c --- /dev/null +++ b/src/packages/abi/classes/ABIConfig.ts @@ -0,0 +1,10 @@ +export default class ABIConfig { + + setAppId(id: string) { + localStorage.setItem('abi_app_id', id); + } + + getAppId(): string { + return localStorage.getItem('abi_app_id'); + } +} \ No newline at end of file From 4d00b7064aabfa3ea046805d31967261c85c9d1c Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 30 Oct 2022 11:29:51 +0530 Subject: [PATCH 21/86] load KMD accounts onload --- src/packages/core-sdk/clients/kmdClient.ts | 35 ++++++++++++- src/redux/explorer/actions/kmd.ts | 59 ++++++++++++++++++++++ src/redux/network/actions/node.ts | 8 +++ src/redux/store.ts | 4 +- 4 files changed, 104 insertions(+), 2 deletions(-) create mode 100644 src/redux/explorer/actions/kmd.ts diff --git a/src/packages/core-sdk/clients/kmdClient.ts b/src/packages/core-sdk/clients/kmdClient.ts index 623faf0f..4084c63d 100644 --- a/src/packages/core-sdk/clients/kmdClient.ts +++ b/src/packages/core-sdk/clients/kmdClient.ts @@ -1,4 +1,4 @@ -import {Account, Kmd} from "algosdk"; +import {Account, Kmd, secretKeyToMnemonic} from "algosdk"; import {CustomTokenHeader, KMDTokenHeader} from "algosdk/dist/types/src/client/urlTokenBaseHTTPClient"; import * as sdk from "algosdk"; import {KMDConnectionParams} from "../types"; @@ -22,6 +22,39 @@ export class KmdClient { return versions; } + async loadKmdAccounts(): Promise { + const mnemonics = []; + const {wallets} = await this.kmd.listWallets(); + let defaultWallet; + + wallets.forEach((wallet) => { + if (wallet.name === 'unencrypted-default-wallet') { + defaultWallet = wallet; + } + }); + + const {wallet_handle_token} = await this.kmd.initWalletHandle(defaultWallet.id, ""); + + try { + const {addresses} = await this.kmd.listKeys(wallet_handle_token); + if (addresses.length > 0) { + const proms = []; + addresses.forEach((addr) => { + proms.push(this.kmd.exportKey(wallet_handle_token, "", addr)); + }); + + const keys = await Promise.all(proms); + + keys.forEach((key) => { + mnemonics.push(secretKeyToMnemonic(key.private_key)); + }) + } + } + catch (e) {} + + return mnemonics; + } + async getDispenserAccount(): Promise { const {wallets} = await this.kmd.listWallets(); let defaultWallet; diff --git a/src/redux/explorer/actions/kmd.ts b/src/redux/explorer/actions/kmd.ts new file mode 100644 index 00000000..943cbb39 --- /dev/null +++ b/src/redux/explorer/actions/kmd.ts @@ -0,0 +1,59 @@ +import {createAsyncThunk, createSlice, PayloadAction} from '@reduxjs/toolkit'; +import {KMDConnectionParams} from "../../../packages/core-sdk/types"; +import {handleException} from "../../common/actions/exception"; +import {KmdClient} from "../../../packages/core-sdk/clients/kmdClient"; +import {getKMDConfig} from "../../../utils/nodeConfig"; + +export interface Kmd { + loading: boolean, + mnemonics: string[] +} + +const initialState: Kmd = { + loading: false, + mnemonics: [] +} + +export const loadKmdAccounts = createAsyncThunk( + 'kmd/loadKmdAccounts', + async (_, thunkAPI) => { + const {dispatch} = thunkAPI; + try { + dispatch(setLoading(true)); + const params: KMDConnectionParams = getKMDConfig(); + const kmdClient = new KmdClient(params); + const accounts = await kmdClient.loadKmdAccounts(); + dispatch(setLoading(false)); + + return accounts; + } + catch (e: any) { + dispatch(setLoading(false)); + dispatch(handleException(e)); + } + } +); + + +export const kmdSlice = createSlice({ + name: 'kmd', + initialState, + reducers: { + setLoading: (state, action: PayloadAction ) => { + state.loading = action.payload; + } + }, + extraReducers: (builder) => { + builder.addCase(loadKmdAccounts.fulfilled, (state, action: PayloadAction) => { + let mnemonics = action.payload; + + if (mnemonics) { + mnemonics = mnemonics.filter((item, index) => mnemonics.indexOf(item) === index);//remove duplicates + state.mnemonics = mnemonics; + } + }); + }, +}); + +export const {setLoading} = kmdSlice.actions +export default kmdSlice.reducer \ No newline at end of file diff --git a/src/redux/network/actions/node.ts b/src/redux/network/actions/node.ts index 0232df37..95a3416e 100644 --- a/src/redux/network/actions/node.ts +++ b/src/redux/network/actions/node.ts @@ -3,6 +3,8 @@ import {A_Genesis, A_Health, A_Status, A_VersionsCheck} from "../../../packages/ import explorer from "../../../utils/dappflow"; import {handleException} from "../../common/actions/exception"; import {NodeClient} from "../../../packages/core-sdk/clients/nodeClient"; +import {CoreNode} from "../../../packages/core-sdk/classes/core/CoreNode"; +import {loadKmdAccounts} from "../../explorer/actions/kmd"; export interface Node { loading: boolean, @@ -80,6 +82,12 @@ export const loadNodeDetails = createAsyncThunk( dispatch(setHealth(health)); dispatch(setLoading(false)); + + const nodeInstance = new CoreNode(status, versionsCheck, genesis, health); + if (nodeInstance.isSandbox()) { + dispatch(loadKmdAccounts()); + } + } catch (e: any) { dispatch(setLoading(false)); diff --git a/src/redux/store.ts b/src/redux/store.ts index 06d077bd..a72a02fb 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -18,6 +18,7 @@ import arcs from "./arcPortal/actions/arcs"; import arc from "./arcPortal/actions/arc"; import node from "./network/actions/node"; import app from "./app/actions/app"; +import kmd from "./explorer/actions/kmd"; export const store = configureStore({ reducer: { @@ -39,7 +40,8 @@ export const store = configureStore({ arcs: arcs, arc: arc, node: node, - app: app + app: app, + kmd: kmd }, }); From 2696cd261e784440850e25f174ecef36f82a24b0 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 30 Oct 2022 13:00:37 +0530 Subject: [PATCH 22/86] show signer account while executing ABI method --- .../ABIMethodExecutor/ABIMethodExecutor.scss | 11 +++- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 64 ++++++++++++++++--- .../TransactionBuilder.scss | 7 -- .../TransactionBuilder/TransactionBuilder.tsx | 17 ----- 4 files changed, 66 insertions(+), 33 deletions(-) delete mode 100644 src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss delete mode 100644 src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss index c16acfa2..2bfa75c6 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss @@ -22,11 +22,20 @@ min-height: 500px; border-right: 1px solid $color-grey-light; padding: 0 15px 0 0; + .abi-method-metadata { + .metadata-item { + font-size: 14px; + margin: 10px 0; + } + } .abi-method-args-form-wrapper { .abi-method-args-form-container { + margin-top: 20px; + padding-top: 10px; + border-top: 1px solid $color-grey-light; .abi-method-args-form-title { font-weight: bold; - margin-bottom: 20px; + text-decoration: underline; } .abi-method-arg { margin: 15px 0; diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 9ebbe707..08dc33fb 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -1,6 +1,6 @@ import './ABIMethodExecutor.scss'; -import React from "react"; -import {ABIMethod, ABIMethodParams} from "algosdk"; +import React, {useEffect, useState} from "react"; +import {ABIMethod, ABIMethodParams, mnemonicToSecretKey} from "algosdk"; import { Button, Dialog, @@ -13,6 +13,12 @@ import { import {CancelOutlined} from "@mui/icons-material"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {theme} from "../../../../theme"; +import {useSelector} from "react-redux"; +import {RootState} from "../../../../redux/store"; +import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; +import {CoreNode} from "../../../../packages/core-sdk/classes/core/CoreNode"; +import {ellipseString} from "../../../../packages/core-sdk/utils"; + const ShadedInput = styled(InputBase)(({ theme }) => { return { @@ -43,17 +49,53 @@ const defaultProps: ABIMethodExecutorProps = { } }; +interface ABIMethodExecutorState{ + appId: number, + signer: string +} + +const initialState: ABIMethodExecutorState = { + appId: 0, + signer: '' +}; + function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.method, handleClose}: ABIMethodExecutorProps): JSX.Element { + const [ + {appId, signer}, + setState + ] = useState({ + ...initialState, + appId: new ABIConfig().getAppId() + }); + + + const abiMethodInstance = new ABIMethod(method); + const args = abiMethodInstance.args; + const node = useSelector((state: RootState) => state.node); + const {status, versionsCheck, genesis, health} = node; + const kmd = useSelector((state: RootState) => state.kmd); + const {mnemonics} = kmd; + const accounts = mnemonics.map((mnemonic) => { + return mnemonicToSecretKey(mnemonic); + }) + + useEffect(() => { + const isSandbox = new CoreNode(status, versionsCheck, genesis, health).isSandbox(); + if (isSandbox) { + if (accounts.length > 0) { + setState(prevState => ({...prevState, signer: accounts[0].addr})); + } + } + }, [show, status, versionsCheck, genesis, health, accounts]); + + function onClose(ev) { handleClose(); ev.preventDefault(); ev.stopPropagation(); } - const abiMethodInstance = new ABIMethod(method); - const args = abiMethodInstance.args; - return (
@@ -95,11 +137,17 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
- {/**/} - +
+
+ Application ID : {appId} +
+
+ Signer : {signer ? ellipseString(signer, 30) : ''} +
+
- {/*
Arguments
*/} +
Arguments
{args.map((arg) => { return
{`${arg.name} (${arg.type.toString()})`} diff --git a/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss b/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss deleted file mode 100644 index cd334181..00000000 --- a/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.scss +++ /dev/null @@ -1,7 +0,0 @@ -@import "src/assets/colors"; - -.transaction-builder-wrapper { - .transaction-builder-container { - - } -} \ No newline at end of file diff --git a/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx b/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx deleted file mode 100644 index 6c953105..00000000 --- a/src/components/Modules/TransactionStudio/TransactionBuilder/TransactionBuilder.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import './TransactionBuilder.scss'; -import React, {} from "react"; - -type TransactionBuilderProps = { - -}; - -function TransactionBuilder({}: TransactionBuilderProps): JSX.Element { - - return (
-
- -
-
); -} - -export default TransactionBuilder; From 9098a7079e761d588881bac71c01a4c843f01394 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 3 Nov 2022 16:02:44 +0530 Subject: [PATCH 23/86] pass method arguments to executor --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 40 ++++++++++++++- src/packages/abi/classes/ABIMethodExecutor.ts | 51 ++++++++++++++++++- .../core-sdk/clients/transactionClient.ts | 7 ++- 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 08dc33fb..3aadd200 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -1,6 +1,10 @@ import './ABIMethodExecutor.scss'; import React, {useEffect, useState} from "react"; -import {ABIMethod, ABIMethodParams, mnemonicToSecretKey} from "algosdk"; +import { + ABIMethod, + ABIMethodParams, + mnemonicToSecretKey +} from "algosdk"; import { Button, Dialog, @@ -13,11 +17,14 @@ import { import {CancelOutlined} from "@mui/icons-material"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {theme} from "../../../../theme"; -import {useSelector} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; import {RootState} from "../../../../redux/store"; import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; import {CoreNode} from "../../../../packages/core-sdk/classes/core/CoreNode"; import {ellipseString} from "../../../../packages/core-sdk/utils"; +import {showSnack} from "../../../../redux/common/actions/snackbar"; +import {handleException} from "../../../../redux/common/actions/exception"; +import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -61,6 +68,7 @@ const initialState: ABIMethodExecutorState = { function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.method, handleClose}: ABIMethodExecutorProps): JSX.Element { + const dispatch = useDispatch(); const [ {appId, signer}, setState @@ -96,6 +104,33 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth ev.stopPropagation(); } + async function execute() { + if (!appId) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid Application ID.' + })); + return; + } + if (!signer) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid Signer.' + })); + return; + } + + try { + const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); + const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), signer); + const signedTxn = unsignedTxns[0].txn.signTxn(accounts[0].sk); + console.log(signedTxn); + } + catch (e: any) { + dispatch(handleException(e)); + } + } + return (
@@ -170,6 +205,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth startIcon={} variant={"contained"} className="black-button" + onClick={execute} >Execute
diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index eca76428..6196b592 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -1,5 +1,14 @@ -import {ABIArgumentType, ABIMethod, ABIMethodParams, ABITransactionType, abiTypeIsTransaction} from "algosdk"; +import { + ABIArgumentType, + ABIMethod, + ABIMethodParams, + ABITransactionType, + abiTypeIsTransaction, + AtomicTransactionComposer, TransactionWithSigner +} from "algosdk"; import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; +import {TransactionClient} from "../../core-sdk/clients/transactionClient"; +import dappflow from "../../../utils/dappflow"; export default class ABIMethodExecutor { method: ABIMethodParams @@ -49,4 +58,44 @@ export default class ABIMethodExecutor { return txnTypes; } + parseArgumentValue(val: any, dataType: string) { + switch (dataType) { + case "uint64": + case "byte": + return BigInt(val); + case "bool": + return Boolean(val); + default: + return val; + } + } + + async getUnsignedTxns(appId: number, from: string, args: any[] = []): Promise { + const atc = new AtomicTransactionComposer(); + + const sp = await new TransactionClient(dappflow.network).getSuggestedParams(); + + const appCallParams = { + appID: appId, + sender: from, + suggestedParams:sp, + signer: undefined + } + + const methodArgs = args.map((arg) => + this.parseArgumentValue( + arg.value, + arg.type + ) + ).filter((value) => value !== undefined && value !== "" && value !== null); + + atc.addMethodCall({ + method: new ABIMethod(this.method), + methodArgs: methodArgs, + ...appCallParams + }); + + const unsignedTxns = atc.buildGroup(); + return unsignedTxns; + } } \ No newline at end of file diff --git a/src/packages/core-sdk/clients/transactionClient.ts b/src/packages/core-sdk/clients/transactionClient.ts index 8795adff..bf1d15a1 100644 --- a/src/packages/core-sdk/clients/transactionClient.ts +++ b/src/packages/core-sdk/clients/transactionClient.ts @@ -1,4 +1,4 @@ -import {Algodv2} from "algosdk"; +import {Algodv2, SuggestedParams} from "algosdk"; import IndexerClient from "algosdk/dist/types/src/client/v2/indexer/indexer"; import {Network} from "../network"; import {A_SearchTransaction} from "../types"; @@ -34,4 +34,9 @@ export class TransactionClient { const {transactions} = await this.indexer.searchForTransactions().txid(id).do(); return transactions[0]; } + + async getSuggestedParams(): Promise{ + const sp = await this.client.getTransactionParams().do(); + return sp; + } } \ No newline at end of file From 4ebb234f49099ead9c1d3f69179e4fc8bfeee941 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 3 Nov 2022 17:21:08 +0530 Subject: [PATCH 24/86] process executor arguments --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 35 ++++++++++++++++--- src/packages/abi/classes/ABIMethodExecutor.ts | 20 ++++++----- src/packages/abi/types.ts | 11 ++++-- 3 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 3aadd200..73a0533d 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -25,6 +25,7 @@ import {ellipseString} from "../../../../packages/core-sdk/utils"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {handleException} from "../../../../redux/common/actions/exception"; import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; +import {A_ABI_METHOD_EXECUTOR_ARG} from "../../../../packages/abi/types"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -58,19 +59,21 @@ const defaultProps: ABIMethodExecutorProps = { interface ABIMethodExecutorState{ appId: number, - signer: string + signer: string, + executorArgs: A_ABI_METHOD_EXECUTOR_ARG[] } const initialState: ABIMethodExecutorState = { appId: 0, - signer: '' + signer: '', + executorArgs: [] }; function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.method, handleClose}: ABIMethodExecutorProps): JSX.Element { const dispatch = useDispatch(); const [ - {appId, signer}, + {appId, signer, executorArgs}, setState ] = useState({ ...initialState, @@ -80,6 +83,9 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const abiMethodInstance = new ABIMethod(method); const args = abiMethodInstance.args; + + + const node = useSelector((state: RootState) => state.node); const {status, versionsCheck, genesis, health} = node; const kmd = useSelector((state: RootState) => state.kmd); @@ -88,6 +94,18 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth return mnemonicToSecretKey(mnemonic); }) + useEffect(() => { + const processedArgs: A_ABI_METHOD_EXECUTOR_ARG[] = []; + args.forEach((arg) => { + processedArgs.push({ + ...arg, + value: '' + }); + setState(prevState => ({...prevState, executorArgs: processedArgs})); + }); + }, []); + + useEffect(() => { const isSandbox = new CoreNode(status, versionsCheck, genesis, health).isSandbox(); if (isSandbox) { @@ -122,7 +140,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth try { const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); - const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), signer); + const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), signer, executorArgs); const signedTxn = unsignedTxns[0].txn.signTxn(accounts[0].sk); console.log(signedTxn); } @@ -183,13 +201,20 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
Arguments
- {args.map((arg) => { + {executorArgs.map((arg, index) => { return
{`${arg.name} (${arg.type.toString()})`} { + const processedArgs = executorArgs; + processedArgs[index] = { + ...arg, + value: ev.target.value + }; + setState(prevState => ({...prevState, executorArgs: processedArgs})); }} fullWidth/>
diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 6196b592..70c93fc1 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -6,7 +6,7 @@ import { abiTypeIsTransaction, AtomicTransactionComposer, TransactionWithSigner } from "algosdk"; -import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; +import {A_ABI_METHOD_EXECUTOR_ARG, ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; import {TransactionClient} from "../../core-sdk/clients/transactionClient"; import dappflow from "../../../utils/dappflow"; @@ -23,7 +23,7 @@ export default class ABIMethodExecutor { canExecute(): boolean { if (this.isGroup()) { - return false + return false; } let supported = true; @@ -58,10 +58,15 @@ export default class ABIMethodExecutor { return txnTypes; } - parseArgumentValue(val: any, dataType: string) { + parseArgumentValue(arg: A_ABI_METHOD_EXECUTOR_ARG): any { + const dataType = arg.type.toString(); + const val = arg.value; + switch (dataType) { case "uint64": case "byte": + case "asset": + case "application": return BigInt(val); case "bool": return Boolean(val); @@ -70,7 +75,7 @@ export default class ABIMethodExecutor { } } - async getUnsignedTxns(appId: number, from: string, args: any[] = []): Promise { + async getUnsignedTxns(appId: number, from: string, args: A_ABI_METHOD_EXECUTOR_ARG[] = []): Promise { const atc = new AtomicTransactionComposer(); const sp = await new TransactionClient(dappflow.network).getSuggestedParams(); @@ -83,10 +88,7 @@ export default class ABIMethodExecutor { } const methodArgs = args.map((arg) => - this.parseArgumentValue( - arg.value, - arg.type - ) + this.parseArgumentValue(arg) ).filter((value) => value !== undefined && value !== "" && value !== null); atc.addMethodCall({ @@ -95,7 +97,7 @@ export default class ABIMethodExecutor { ...appCallParams }); - const unsignedTxns = atc.buildGroup(); + const unsignedTxns= atc.buildGroup(); return unsignedTxns; } } \ No newline at end of file diff --git a/src/packages/abi/types.ts b/src/packages/abi/types.ts index 290012ef..826e1ba5 100644 --- a/src/packages/abi/types.ts +++ b/src/packages/abi/types.ts @@ -1,4 +1,4 @@ -import {ABIContractParams, ABITransactionType} from "algosdk"; +import {ABIArgumentType, ABIContractParams, ABITransactionType} from "algosdk"; export interface A_Application_ABI { id?: number, @@ -7,4 +7,11 @@ export interface A_Application_ABI { abi: ABIContractParams; } -export const ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES: ABITransactionType[] = [ABITransactionType.pay, ABITransactionType.axfer]; \ No newline at end of file +export const ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES: ABITransactionType[] = [ABITransactionType.pay, ABITransactionType.axfer]; + +export interface A_ABI_METHOD_EXECUTOR_ARG { + type: ABIArgumentType, + name?: string, + description?: string, + value: any +} \ No newline at end of file From 64b9c4e8d70cd6d1757a60cd2ef574c1563ea91e Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 3 Nov 2022 18:53:56 +0530 Subject: [PATCH 25/86] integrate wallet signers --- package.json | 1 + .../ABIMethodExecutor/ABIMethodExecutor.tsx | 15 ++- src/packages/abi/classes/ABIMethodExecutor.ts | 19 +++- .../core-sdk/clients/transactionClient.ts | 4 + src/packages/signers/adapter.ts | 52 +++++++++ src/packages/signers/algoSigner.ts | 107 ++++++++++++++++++ src/packages/signers/constants/index.ts | 30 +++++ src/packages/signers/index.ts | 4 + src/packages/signers/logicSigner.ts | 26 +++++ src/packages/signers/myAlgoWalletSigner.ts | 73 ++++++++++++ src/packages/signers/types.ts | 16 +++ src/packages/signers/walletSigner.ts | 44 +++++++ yarn.lock | 12 ++ 13 files changed, 397 insertions(+), 6 deletions(-) create mode 100644 src/packages/signers/adapter.ts create mode 100644 src/packages/signers/algoSigner.ts create mode 100644 src/packages/signers/constants/index.ts create mode 100644 src/packages/signers/index.ts create mode 100644 src/packages/signers/logicSigner.ts create mode 100644 src/packages/signers/myAlgoWalletSigner.ts create mode 100644 src/packages/signers/types.ts create mode 100644 src/packages/signers/walletSigner.ts diff --git a/package.json b/package.json index 6e635e41..0896e82a 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@mui/lab": "^5.0.0-alpha.88", "@mui/material": "^5.6.0", "@mui/x-data-grid": "^5.8.0", + "@randlabs/myalgo-connect": "^1.4.0", "@reduxjs/toolkit": "^1.8.1", "@testing-library/jest-dom": "^5.14.1", "@testing-library/react": "^12.0.0", diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 73a0533d..4faebd98 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -58,13 +58,13 @@ const defaultProps: ABIMethodExecutorProps = { }; interface ABIMethodExecutorState{ - appId: number, + appId: string, signer: string, executorArgs: A_ABI_METHOD_EXECUTOR_ARG[] } const initialState: ABIMethodExecutorState = { - appId: 0, + appId: '', signer: '', executorArgs: [] }; @@ -94,6 +94,10 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth return mnemonicToSecretKey(mnemonic); }) + const clearState = () => { + setState({ ...initialState }); + }; + useEffect(() => { const processedArgs: A_ABI_METHOD_EXECUTOR_ARG[] = []; args.forEach((arg) => { @@ -103,7 +107,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth }); setState(prevState => ({...prevState, executorArgs: processedArgs})); }); - }, []); + }, [show]); useEffect(() => { @@ -118,6 +122,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth function onClose(ev) { handleClose(); + clearState(); ev.preventDefault(); ev.stopPropagation(); } @@ -141,8 +146,8 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth try { const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), signer, executorArgs); - const signedTxn = unsignedTxns[0].txn.signTxn(accounts[0].sk); - console.log(signedTxn); + const signedTxns = await abiMethodExecutorInstance.signMethodTxns(unsignedTxns, accounts[0]); + await abiMethodExecutorInstance.execute(signedTxns); } catch (e: any) { dispatch(handleException(e)); diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 70c93fc1..b896681e 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -3,12 +3,13 @@ import { ABIMethod, ABIMethodParams, ABITransactionType, - abiTypeIsTransaction, + abiTypeIsTransaction, Account, AtomicTransactionComposer, TransactionWithSigner } from "algosdk"; import {A_ABI_METHOD_EXECUTOR_ARG, ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; import {TransactionClient} from "../../core-sdk/clients/transactionClient"; import dappflow from "../../../utils/dappflow"; +import {WalletSigner} from "../../signers"; export default class ABIMethodExecutor { method: ABIMethodParams @@ -100,4 +101,20 @@ export default class ABIMethodExecutor { const unsignedTxns= atc.buildGroup(); return unsignedTxns; } + + async signMethodTxns(unsignedTxns: TransactionWithSigner[], account: Account): Promise { + const signer = new WalletSigner(account); + const txns = []; + unsignedTxns.forEach((unsignedTxn) => { + txns.push(unsignedTxn.txn); + }); + const signedTxns = signer.signGroupTxns(txns); + return signedTxns + } + + async execute(signedTxns: Uint8Array[]) { + const txnClient = new TransactionClient(dappflow.network); + const resp = await txnClient.send(signedTxns); + console.log(resp); + } } \ No newline at end of file diff --git a/src/packages/core-sdk/clients/transactionClient.ts b/src/packages/core-sdk/clients/transactionClient.ts index bf1d15a1..5c0b250d 100644 --- a/src/packages/core-sdk/clients/transactionClient.ts +++ b/src/packages/core-sdk/clients/transactionClient.ts @@ -39,4 +39,8 @@ export class TransactionClient { const sp = await this.client.getTransactionParams().do(); return sp; } + + async send(txns: Uint8Array | Uint8Array[]): Promise { + return await this.client.sendRawTransaction(txns).do(); + } } \ No newline at end of file diff --git a/src/packages/signers/adapter.ts b/src/packages/signers/adapter.ts new file mode 100644 index 00000000..3afe2c7b --- /dev/null +++ b/src/packages/signers/adapter.ts @@ -0,0 +1,52 @@ +import {SIGNERS} from "./constants"; +import {Signer} from "./types"; +import {WalletSigner} from "./walletSigner"; +import {BrowserAlgoSigner} from "./algoSigner"; +import {LogicSigner} from "./logicSigner"; +import {MyAlgoWalletSigner} from "./myAlgoWalletSigner"; + +const ws = new WalletSigner(); +const as = new BrowserAlgoSigner(); +const ls = new LogicSigner(); +const maws = new MyAlgoWalletSigner(); + +export function getSigner(name: string): Signer{ + if (name === SIGNERS.WALLET) { + return ws; + } + else if (name === SIGNERS.ALGO_SIGNER) { + return as; + } + else if (name === SIGNERS.LOGIC_SIG) { + return ls; + } + else if (name === SIGNERS.MY_ALGO_WALLET) { + return maws; + } + + return ws; +} + +export interface SupportedSigner { + name: string + label: string + logo: string + instance: Signer +} + +export function getSupportedSigners(): SupportedSigner[] { + return [ + { + name: SIGNERS.ALGO_SIGNER, + label: 'AlgoSigner', + instance: getSigner(SIGNERS.ALGO_SIGNER), + logo: 'data:image/jpeg+xml;base64,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' + }, + { + name: SIGNERS.MY_ALGO_WALLET, + label: 'MyAlgo Wallet', + instance: getSigner(SIGNERS.MY_ALGO_WALLET), + logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMCIgaGVpZ2h0PSIzMCIgdmlld0JveD0iMCAwIDMwIDMwIj4KICAgIDxwYXRoIGlkPSJwcmVmaXhfX1N1YnRyYWN0aW9uXzExIiBmaWxsPSIjMjQ1ZWM3IiBkPSJNMTUgMzBBMTUgMTUgMCAwIDEgNC4zOTIgNC4zOTMgMTUgMTUgMCAxIDEgMjUuNiAyNS42MDYgMTQuOSAxNC45IDAgMCAxIDE1IDMwem0zLjk5MS0xOS41MDhsLjEyMi40NjggMi40NTkgOC45MWgyTDIwLjIxNCA4LjMxNCAyMC4xMzIgOGgtMS43NDVsLS4wNC4wNjMtMS42MzMgMi45LTEuNjc0IDIuOTc0LS4wNC4wNzEtLjAxOS0uMDcxLS4yLS43NjQtLjU3MS0yLjIxLS4wNjEtLjIyLS42MzMtMi40MjlMMTMuNDMgOGgtMS43NDVsLS4wNDEuMDYzLTEuNjMzIDIuOS0xLjY3MyAyLjk3NEw2LjY3MyAxNi45IDUgMTkuODczaDJMOC42NzQgMTYuOWwxLjY3NC0yLjk2MyAxLjY2My0yLjk3NC4yNzUtLjQ3MS4xMjIuNDcxLjUxIDEuOTU4LjYzNCAyLjQzOS4yMi44MzItLjQuNzA3LTEuNjcyIDIuOTc0aDJsLjcwNy0xLjI1NSAxLjIyOC0yLjE3OSAxLjQxNC0yLjUgMS42NjMtMi45NzQuMjc0LS40Njl6IiBkYXRhLW5hbWU9IlN1YnRyYWN0aW9uIDExIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSguMDAyKSIvPgo8L3N2Zz4K' + } + ]; +} \ No newline at end of file diff --git a/src/packages/signers/algoSigner.ts b/src/packages/signers/algoSigner.ts new file mode 100644 index 00000000..b5efd9a3 --- /dev/null +++ b/src/packages/signers/algoSigner.ts @@ -0,0 +1,107 @@ +import {Signer, SignerAccount} from "./types"; +import {Transaction} from "algosdk"; +import {ALGO_SIGNER_NET, NETWORKS} from "./constants"; + +export class BrowserAlgoSigner implements Signer{ + private supportedNetworks: string[]; + + constructor() { + this.supportedNetworks = [NETWORKS.TESTNET, NETWORKS.MAINNET]; + } + + async signTxn(unsignedTxn: Transaction): Promise { + const byteTxn: Uint8Array = unsignedTxn.toByte(); + // @ts-ignore + const b64Txn = AlgoSigner.encoding.msgpackToBase64(byteTxn); + + // @ts-ignore + const signedTxns: any[] = await AlgoSigner.signTxn([ + {txn: b64Txn}, + ]); + + // @ts-ignore + const rawSignedTxn: Uint8Array = AlgoSigner.encoding.base64ToMsgpack(signedTxns[0].blob); + return rawSignedTxn; + } + + async signGroupTxns(unsignedTxns: Transaction[]): Promise { + const txns: any[] = []; + + unsignedTxns.forEach((unsignedTxn) => { + const byteTxn: Uint8Array = unsignedTxn.toByte(); + // @ts-ignore + const b64Txn = AlgoSigner.encoding.msgpackToBase64(byteTxn); + txns.push({ + txn: b64Txn + }); + }); + + // @ts-ignore + const signedTxns = await AlgoSigner.signTxn(txns); + + const rawSignedTransactions: Uint8Array[] = []; + + signedTxns.forEach((signedTxn) => { + // @ts-ignore + rawSignedTransactions.push(AlgoSigner.encoding.base64ToMsgpack(signedTxn.blob)); + }); + + return rawSignedTransactions; + } + + isInstalled(): boolean { + // @ts-ignore + return typeof AlgoSigner !== 'undefined'; + } + + isNetworkSupported(name: string): boolean { + return this.supportedNetworks.indexOf(name) !== -1; + } + + getAlgoSignerNet(name: string): string { + if (name === NETWORKS.MAINNET) { + return ALGO_SIGNER_NET.MAINNET + } + if (name === NETWORKS.BETANET) { + return ALGO_SIGNER_NET.BETANET + } + if (name === NETWORKS.TESTNET) { + return ALGO_SIGNER_NET.TESTNET + } + } + + async connect(name: string): Promise { + if (this.isInstalled()) { + if (this.isNetworkSupported(name)) { + const accounts: SignerAccount[] = []; + // @ts-ignore + const connection = await AlgoSigner.connect(); + // @ts-ignore + const wallets = await AlgoSigner.accounts({ + ledger: this.getAlgoSignerNet(name) + }); + + if (wallets) { + wallets.forEach((wallet) => { + accounts.push({ + address: wallet.address, + name: wallet.name + }); + }); + } + + return accounts; + } + else { + throw new Error(name + " is not supported by AlgoSigner"); + } + } + else { + throw new Error("Algosigner is not installed"); + } + } + + logout() { + + } +} \ No newline at end of file diff --git a/src/packages/signers/constants/index.ts b/src/packages/signers/constants/index.ts new file mode 100644 index 00000000..8432223b --- /dev/null +++ b/src/packages/signers/constants/index.ts @@ -0,0 +1,30 @@ +export enum NETWORKS { + BETANET = "betanet", + TESTNET = 'testnet', + MAINNET = 'mainnet' +} + +export enum SIGNERS { + WALLET = 'wallet', + ALGO_SIGNER = 'algo_signer', + LOGIC_SIG = 'logic_sig', + MY_ALGO_WALLET = 'my_algo_wallet' +} + +export enum ALGO_SIGNER_NET { + BETANET = "BetaNet", + TESTNET = 'TestNet', + MAINNET = 'MainNet' +} + +export enum LOCAL_STORAGE { + NETWORK = 'network' +} + +export const BURN_ADDRESS_MIN_BAL: number = 0.2; + +export enum NFT_STANDARDS { + ARC3 = "arc3", + ARC69 = 'arc69', +} +export const IPFS_GATEWAY = 'https://ipfs.io/ipfs'; \ No newline at end of file diff --git a/src/packages/signers/index.ts b/src/packages/signers/index.ts new file mode 100644 index 00000000..39c85e32 --- /dev/null +++ b/src/packages/signers/index.ts @@ -0,0 +1,4 @@ +export * from './walletSigner'; +export * from './algoSigner'; +export * from './logicSigner'; +export * from './adapter'; diff --git a/src/packages/signers/logicSigner.ts b/src/packages/signers/logicSigner.ts new file mode 100644 index 00000000..8cf380a2 --- /dev/null +++ b/src/packages/signers/logicSigner.ts @@ -0,0 +1,26 @@ +import {Signer} from "./types"; +import * as sdk from "algosdk"; +import {NETWORKS} from "./constants"; +import {LogicSigAccount} from "algosdk"; + +export class LogicSigner implements Signer{ + + private supportedNetworks: string[]; + + constructor() { + this.supportedNetworks = [NETWORKS.BETANET, NETWORKS.TESTNET, NETWORKS.MAINNET]; + } + + async signTxnByLogic(unsignedTxn, logic: string): Promise { + const logicSig = new LogicSigAccount(new Uint8Array(Buffer.from(logic, "base64"))); + return sdk.signLogicSigTransactionObject(unsignedTxn, logicSig).blob; + } + + isInstalled(): boolean { + return true; + } + + logout() { + + } +} diff --git a/src/packages/signers/myAlgoWalletSigner.ts b/src/packages/signers/myAlgoWalletSigner.ts new file mode 100644 index 00000000..31a3f144 --- /dev/null +++ b/src/packages/signers/myAlgoWalletSigner.ts @@ -0,0 +1,73 @@ +import {Signer, SignerAccount} from "./types"; +import {Transaction} from "algosdk"; +import MyAlgoConnect from '@randlabs/myalgo-connect'; +import {NETWORKS} from "./constants"; + + +export class MyAlgoWalletSigner implements Signer{ + private readonly myAlgoConnect: MyAlgoConnect; + private supportedNetworks: string[]; + + constructor() { + this.myAlgoConnect = new MyAlgoConnect(); + this.supportedNetworks = [NETWORKS.BETANET, NETWORKS.TESTNET, NETWORKS.MAINNET]; + } + + async signTxn(unsignedTxn: Transaction): Promise { + const byteTxn = unsignedTxn.toByte(); + const signedTxn = await this.myAlgoConnect.signTransaction(byteTxn); + return signedTxn.blob; + } + + async signGroupTxns(unsignedTxns: Transaction[]): Promise { + const encodedTransactionObjs = []; + unsignedTxns.forEach((unsignedTxn) => { + encodedTransactionObjs.push(unsignedTxn.toByte()); + }); + + const blobs = []; + const signedTxns = await this.myAlgoConnect.signTransaction(encodedTransactionObjs); + signedTxns.forEach((signedTxn) => { + blobs.push(signedTxn.blob); + }); + + return blobs; + } + + async connect(name: string): Promise { + if (this.isInstalled()) { + if (this.isNetworkSupported(name)) { + const accounts: SignerAccount[] = []; + const wallets = await this.myAlgoConnect.connect(); + if (wallets) { + wallets.forEach((wallet) => { + accounts.push({ + address: wallet.address, + name: wallet.name + }); + }); + } + + return accounts; + } + else { + throw new Error(name + " is not supported by MyAlgo Wallet"); + } + } + else { + throw new Error("MyAlgo Wallet is not installed"); + } + } + + isInstalled(): boolean { + return true; + } + + isNetworkSupported(name: string): boolean { + return this.supportedNetworks.indexOf(name) !== -1; + } + + logout() { + + } +} \ No newline at end of file diff --git a/src/packages/signers/types.ts b/src/packages/signers/types.ts new file mode 100644 index 00000000..42efe2f9 --- /dev/null +++ b/src/packages/signers/types.ts @@ -0,0 +1,16 @@ +import {Transaction} from "algosdk"; + +export interface SignerAccount { + address: string, + name: string +} + +export interface Signer { + signTxn?(unsignedTxn: Transaction): Uint8Array | Promise; + signGroupTxns?(unsignedTxns: Transaction[]): Uint8Array[] | Promise; + signTxnByLogic?(unsignedTxn, logic: string): Promise; + isInstalled(): boolean; + connect?(name: string): Promise, + isNetworkSupported?(name: string): boolean, + logout(): void +} \ No newline at end of file diff --git a/src/packages/signers/walletSigner.ts b/src/packages/signers/walletSigner.ts new file mode 100644 index 00000000..8795ef10 --- /dev/null +++ b/src/packages/signers/walletSigner.ts @@ -0,0 +1,44 @@ +import {Signer} from "./types"; +import {Account, Transaction} from "algosdk"; +import {NETWORKS} from "./constants"; + +export class WalletSigner implements Signer{ + private wallet: Account; + private supportedNetworks: string[]; + + constructor(wallet?: Account) { + if (wallet) { + this.setWallet(wallet); + } + this.supportedNetworks = [NETWORKS.BETANET, NETWORKS.TESTNET, NETWORKS.MAINNET]; + } + + setWallet(wallet: Account): void { + this.wallet = wallet; + } + + signTxn(unsignedTxn: Transaction): Uint8Array { + const {sk} = this.wallet; + const signedRawTxn = unsignedTxn.signTxn(sk); + return signedRawTxn; + } + + signGroupTxns(unsignedTxns: Transaction[]): Uint8Array[] { + const signedTxns: Uint8Array[] = []; + + unsignedTxns.forEach((unsignedTxn) => { + const test = this.signTxn(unsignedTxn); + signedTxns.push(test); + }); + + return signedTxns; + } + + isInstalled(): boolean { + return true; + } + + logout() { + + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index bbba8f9d..d2c4ad41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2164,6 +2164,18 @@ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.5.tgz#db5a11bf66bdab39569719555b0f76e138d7bd64" integrity sha512-9X2obfABZuDVLCgPK9aX0a/x4jaOEweTTWE2+9sr0Qqqevj2Uv5XorvusThmc9XGYpS9yI+fhh8RTafBtGposw== +"@randlabs/communication-bridge@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@randlabs/communication-bridge/-/communication-bridge-1.0.1.tgz#d1ecfc29157afcbb0ca2d73122d67905eecb5bf3" + integrity sha512-CzS0U8IFfXNK7QaJFE4pjbxDGfPjbXBEsEaCn9FN15F+ouSAEUQkva3Gl66hrkBZOGexKFEWMwUHIDKpZ2hfVg== + +"@randlabs/myalgo-connect@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@randlabs/myalgo-connect/-/myalgo-connect-1.4.0.tgz#1446d527978b7b5666562a4e921a51262a29cddd" + integrity sha512-sAeYbnx4HOLVXNaTFpoI2K0BmdC4rqzKqb4wuUbk51ay1oQ0jnfOgwS1Ms8uZchoaVNLVlMPK9nso1J/CAOFnw== + dependencies: + "@randlabs/communication-bridge" "1.0.1" + "@reduxjs/toolkit@^1.8.1": version "1.8.1" resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.8.1.tgz#94ee1981b8cf9227cda40163a04704a9544c9a9f" From 720dbc2b95fd2c24fb702e4f20881ef0770c1610 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 3 Nov 2022 22:45:46 +0530 Subject: [PATCH 26/86] bug fix --- .../ABI/ABIMethodExecutor/ABIMethodExecutor.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 4faebd98..c26bbf5a 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -90,9 +90,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const {status, versionsCheck, genesis, health} = node; const kmd = useSelector((state: RootState) => state.kmd); const {mnemonics} = kmd; - const accounts = mnemonics.map((mnemonic) => { - return mnemonicToSecretKey(mnemonic); - }) + const clearState = () => { setState({ ...initialState }); @@ -113,11 +111,14 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth useEffect(() => { const isSandbox = new CoreNode(status, versionsCheck, genesis, health).isSandbox(); if (isSandbox) { - if (accounts.length > 0) { + if (mnemonics.length > 0) { + const accounts = mnemonics.map((mnemonic) => { + return mnemonicToSecretKey(mnemonic); + }) setState(prevState => ({...prevState, signer: accounts[0].addr})); } } - }, [show, status, versionsCheck, genesis, health, accounts]); + }, [show, status, versionsCheck, genesis, health]); function onClose(ev) { @@ -146,7 +147,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth try { const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), signer, executorArgs); - const signedTxns = await abiMethodExecutorInstance.signMethodTxns(unsignedTxns, accounts[0]); + const signedTxns = await abiMethodExecutorInstance.signMethodTxns(unsignedTxns, mnemonicToSecretKey(mnemonics[0])); await abiMethodExecutorInstance.execute(signedTxns); } catch (e: any) { From d7e98b9c5510f11675389b508d72d5c36ea249f5 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 5 Nov 2022 20:27:41 +0530 Subject: [PATCH 27/86] remove future blocks links --- .../NodeStatus/tiles/ProtocolUpgrade/ProtocolUpgrade.tsx | 5 ++--- src/packages/signers/algoSigner.ts | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/Modules/NodeStatus/tiles/ProtocolUpgrade/ProtocolUpgrade.tsx b/src/components/Modules/NodeStatus/tiles/ProtocolUpgrade/ProtocolUpgrade.tsx index 1161af5f..4ba4966a 100644 --- a/src/components/Modules/NodeStatus/tiles/ProtocolUpgrade/ProtocolUpgrade.tsx +++ b/src/components/Modules/NodeStatus/tiles/ProtocolUpgrade/ProtocolUpgrade.tsx @@ -7,7 +7,6 @@ import {useSelector} from "react-redux"; import {RootState} from "../../../../../redux/store"; import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'; import {CoreNode} from "../../../../../packages/core-sdk/classes/core/CoreNode"; -import LinkToBlock from "../../../Explorer/Common/Links/LinkToBlock"; import CheckCircleOutlinedIcon from "@mui/icons-material/CheckCircleOutlined"; @@ -48,13 +47,13 @@ function ProtocolUpgrade(): JSX.Element {
Upgrade round :
- + {coreNodeInstance.getProtocolUpgradeBlock()}
current round :
- + {health.round}
diff --git a/src/packages/signers/algoSigner.ts b/src/packages/signers/algoSigner.ts index b5efd9a3..d57db6cc 100644 --- a/src/packages/signers/algoSigner.ts +++ b/src/packages/signers/algoSigner.ts @@ -75,7 +75,7 @@ export class BrowserAlgoSigner implements Signer{ if (this.isNetworkSupported(name)) { const accounts: SignerAccount[] = []; // @ts-ignore - const connection = await AlgoSigner.connect(); + await AlgoSigner.connect(); // @ts-ignore const wallets = await AlgoSigner.accounts({ ledger: this.getAlgoSignerNet(name) From 4ffe1fe828905362ec95757d2ad370abaf67d505 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 5 Nov 2022 23:53:08 +0530 Subject: [PATCH 28/86] create applicaton modal --- package.json | 2 +- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 26 +- .../Modules/ABI/ABIStudio/ABIStudio.tsx | 2 +- .../AppManager/CreateApp/CreateApp.scss | 21 ++ .../AppManager/CreateApp/CreateApp.tsx | 262 ++++++++++++++++++ .../core-sdk/clients/applicationClient.ts | 7 + src/packages/core-sdk/utils/fileUtils.ts | 12 + yarn.lock | 68 +---- 8 files changed, 331 insertions(+), 69 deletions(-) create mode 100644 src/components/Modules/AppManager/CreateApp/CreateApp.scss create mode 100644 src/components/Modules/AppManager/CreateApp/CreateApp.tsx create mode 100644 src/packages/core-sdk/utils/fileUtils.ts diff --git a/package.json b/package.json index 0896e82a..3d165b5d 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@types/react-dom": "^17.0.9", "@types/react-transition-group": "^4.4.5", "@types/sass-loader": "^8.0.3", - "algosdk": "^1.22.0", + "algosdk": "^1.23.1", "atob": "^2.1.2", "axios": "^0.27.2", "buffer": "^6.0.3", diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 54e29a91..8000a583 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -8,28 +8,32 @@ import ABINetworks from "../ABINetworks/ABINetworks"; import {ABIContract, ABIContractParams} from "algosdk"; import ABIConfig from "../ABIConfig/ABIConfig"; import SettingsIcon from '@mui/icons-material/Settings'; +import CreateApp from "../../AppManager/CreateApp/CreateApp"; type ABIEditorProps = { abi: ABIContractParams, hideNetworks?: boolean, - supportExecutor?: boolean + supportExecutor?: boolean, + supportCreateApp?: boolean }; interface ABIEditorState{ showConfig: boolean, + showCreateApp: boolean, } const initialState: ABIEditorState = { - showConfig: false + showConfig: false, + showCreateApp: false }; -function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false}: ABIEditorProps): JSX.Element { +function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false, supportCreateApp = false}: ABIEditorProps): JSX.Element { const abiInstance = new ABIContract(abi); const networks = abiInstance.networks; const [ - {showConfig}, + {showConfig, showCreateApp}, setState ] = useState(initialState); @@ -50,7 +54,7 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support {supportExecutor ?
{setState(prevState => ({...prevState, showConfig: false}));}}>
: ''} + + {supportCreateApp ?
+ + {setState(prevState => ({...prevState, showCreateApp: false}));}}> +
: ''} +
diff --git a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx index 7d0b6953..bf9c0512 100644 --- a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx +++ b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx @@ -46,7 +46,7 @@ function ABIStudio(): JSX.Element { setState(prevState => ({...prevState, abi, imported: true})); localStorage.setItem('abi', JSON.stringify(abi)); }}> - {imported ? : ''} + {imported ? : ''}
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.scss b/src/components/Modules/AppManager/CreateApp/CreateApp.scss new file mode 100644 index 00000000..b69a58ed --- /dev/null +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.scss @@ -0,0 +1,21 @@ +@import "src/assets/colors"; + +.create-app-content { + padding-top: 20px; + .teal-program { + font-size: 10px; + margin-top: 10px; + word-break: break-all; + background: $color-grey-very-light; + padding: 15px; + border-radius: 10px; + height: 30px; + overflow: auto; + } +} + +.create-app-wrapper { + .create-app-container { + + } +} \ No newline at end of file diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx new file mode 100644 index 00000000..acc248e6 --- /dev/null +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -0,0 +1,262 @@ +import './CreateApp.scss'; +import React, {Fragment, useEffect, useState} from "react"; +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogTitle, FormLabel, Grid, + IconButton, + InputBase, + InputBaseProps, + styled, TextField, Tooltip +} from "@mui/material"; +import {CancelOutlined, CloudUpload, CloudUploadOutlined, FileUploadOutlined} from "@mui/icons-material"; +import {theme} from "../../../../theme"; +import {useDispatch} from "react-redux"; +import {getFileContent} from "../../../../packages/core-sdk/utils/fileUtils"; +import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; +import {handleException} from "../../../../redux/common/actions/exception"; +import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicationClient"; +import dappflow from "../../../../utils/dappflow"; +import {ApplicationParams, CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; +import {TransactionApplication} from "algosdk/dist/types/src/client/v2/indexer/models/types"; + + +const ShadedInput = styled(InputBase)(({ theme }) => { + return { + padding: 5, + paddingLeft: 10, + marginTop: 5, + fontSize: 14, + border: '1px solid ' + theme.palette.grey[200] + }; +}); + +const formLabelStyle = { + marginLeft: '5px', + fontSize: '13px', + fontWeight: 'bold', + color: theme.palette.grey[600] +}; + +interface CreateAppProps{ + show: boolean, + handleClose?: Function +} + +const defaultProps: CreateAppProps = { + show: false +}; + +interface CreateAppState{ + params: { + id: string, + approvalProgram: string, + clearProgram: string, + globalBytes: string, + localBytes: string, + } +} + +const initialState: CreateAppState = { + params: { + id: '', + approvalProgram: '', + clearProgram: '', + globalBytes: '', + localBytes: '' + }, +}; + + +function CreateApp({show = defaultProps.show, handleClose}: CreateAppProps): JSX.Element { + + const dispatch = useDispatch(); + + const [ + {params}, + setState + ] = useState({ + ...initialState + }); + + useEffect(() => { + setState(prevState => ({...initialState})); + }, [show]); + + function onClose(ev) { + handleClose(); + ev.preventDefault(); + ev.stopPropagation(); + } + + async function validateProgram(event): Promise { + let file = event.target.files[0]; + const target = event.target; + + try { + dispatch(showLoader('Reading TEAL program')); + const content = await getFileContent(file); + dispatch(hideLoader()); + + dispatch(showLoader('Compiling program')); + const compileResp = await new ApplicationClient(dappflow.network).compileProgram(content); + dispatch(hideLoader()); + console.log(compileResp); + + target.value = null; + return compileResp; + } + catch (e: any) { + dispatch(hideLoader()); + dispatch(handleException(e)); + } + } + + return (
+
+ + {show ? + +
+
+
Create Application
+
+
+ + + +
+ +
+
+ + +
+
+ + + + Global bytes + { + setState(prevState => ({...prevState, params: { + ...params, + globalBytes: ev.target.value + }})); + } + } + fullWidth/> + + + Local bytes + { + setState(prevState => ({...prevState, params: { + ...params, + localBytes: ev.target.value + }})); + } + } + fullWidth/> + + + Approval program +
+ + {params.approvalProgram ?
+ {params.approvalProgram} +
: ''} + +
+
+ + + Clear program +
+ + {params.clearProgram ?
+ {params.clearProgram} +
: ''} + +
+
+ +
+ +
+ + +
+
+ +
+ + + +
: ''} + + +
+
); +} + +export default CreateApp; diff --git a/src/packages/core-sdk/clients/applicationClient.ts b/src/packages/core-sdk/clients/applicationClient.ts index 9c6b5b4f..6edddeac 100644 --- a/src/packages/core-sdk/clients/applicationClient.ts +++ b/src/packages/core-sdk/clients/applicationClient.ts @@ -6,6 +6,7 @@ import { import {Network} from "../network"; import axios from 'axios'; import {A_TransactionsResponse} from "./transactionClient"; +import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; export type A_ApplicationTransactionsResponse = A_TransactionsResponse; export type A_ApplicationsResponse = { @@ -65,4 +66,10 @@ export class ApplicationClient{ } }); } + + async compileProgram(programSource: string): Promise { + const encoder = new TextEncoder(); + const programBytes = encoder.encode(programSource); + return await this.client.compile(programBytes).do(); + } } \ No newline at end of file diff --git a/src/packages/core-sdk/utils/fileUtils.ts b/src/packages/core-sdk/utils/fileUtils.ts new file mode 100644 index 00000000..ad7abfda --- /dev/null +++ b/src/packages/core-sdk/utils/fileUtils.ts @@ -0,0 +1,12 @@ +export async function getFileContent(file: File): Promise { + const promise = new Promise(function(resolve, reject) { + const fileReader = new FileReader(); + fileReader.onloadend = () => { + const content = fileReader.result; + resolve(content); + }; + fileReader.readAsText(file); + }); + + return promise; +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index d2c4ad41..c6770e12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3232,23 +3232,21 @@ algo-msgpack-with-bigint@^2.1.1: resolved "https://registry.yarnpkg.com/algo-msgpack-with-bigint/-/algo-msgpack-with-bigint-2.1.1.tgz#38bb717220525b3ff42232eefdcd9efb9ad405d6" integrity sha512-F1tGh056XczEaEAqu7s+hlZUDWwOBT70Eq0lfMpBP2YguSQVyxRbprLq5rELXKQOyOaixTWYhMeMQMzP0U5FoQ== -algosdk@^1.22.0: - version "1.22.0" - resolved "https://registry.yarnpkg.com/algosdk/-/algosdk-1.22.0.tgz#7d38232883a4de3bb9403fb9592cdaf0785c8b35" - integrity sha512-oj2G1ucLyqfTAPM9iIWiSfU0Jmwx1gaafqlC2RaWcwHx86cwnFTwEf/haFQ9yoirkIozVlZYTYtv+Ltkj3il8w== +algosdk@^1.23.1: + version "1.23.1" + resolved "https://registry.yarnpkg.com/algosdk/-/algosdk-1.23.1.tgz#c8fbf1f7af42fc722c9b7e9fc9c4a1015f1ede82" + integrity sha512-7fKyTd2V6rsac3ADm6N5jJV80cCw+EIBzXVLzfPvKqranjOZtq7xIqwpEkZgBkZ/TJ5wxwTDJVPyswXChv+QPg== dependencies: algo-msgpack-with-bigint "^2.1.1" buffer "^6.0.2" + cross-fetch "^3.1.5" hi-base32 "^0.5.1" js-sha256 "^0.9.0" js-sha3 "^0.8.0" js-sha512 "^0.8.0" json-bigint "^1.0.0" - superagent "^6.1.0" tweetnacl "^1.0.3" vlq "^2.0.4" - optionalDependencies: - fsevents "2.1.2" ansi-escapes@^4.2.1, ansi-escapes@^4.3.1: version "4.3.2" @@ -4215,11 +4213,6 @@ commondir@^1.0.1: resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= -component-emitter@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - compressible@~2.0.16: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" @@ -4284,11 +4277,6 @@ cookie@0.4.2, cookie@~0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== -cookiejar@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" - integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== - copy-to-clipboard@^3, copy-to-clipboard@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae" @@ -5574,11 +5562,6 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fast-safe-stringify@^2.0.7: - version "2.1.1" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz#c406a83b6e70d9e35ce3b30a81141df30aeba884" - integrity sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA== - fastq@^1.6.0: version "1.13.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" @@ -5816,11 +5799,6 @@ formdata-node@^4.0.0: node-domexception "1.0.0" web-streams-polyfill "4.0.0-beta.1" -formidable@^1.2.2: - version "1.2.6" - resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.6.tgz#d2a51d60162bbc9b4a055d8457a7c75315d1a168" - integrity sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ== - forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -5870,11 +5848,6 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -fsevents@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" - integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== - fsevents@^2.3.2, fsevents@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -7715,7 +7688,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -methods@^1.1.2, methods@~1.1.2: +methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= @@ -7753,11 +7726,6 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.6: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -9026,13 +8994,6 @@ qs@^6.10.2: dependencies: side-channel "^1.0.4" -qs@^6.9.4: - version "6.11.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" - integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== - dependencies: - side-channel "^1.0.4" - querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -10294,23 +10255,6 @@ stylis@4.0.13: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.13.tgz#f5db332e376d13cc84ecfe5dace9a2a51d954c91" integrity sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag== -superagent@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/superagent/-/superagent-6.1.0.tgz#09f08807bc41108ef164cfb4be293cebd480f4a6" - integrity sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg== - dependencies: - component-emitter "^1.3.0" - cookiejar "^2.1.2" - debug "^4.1.1" - fast-safe-stringify "^2.0.7" - form-data "^3.0.0" - formidable "^1.2.2" - methods "^1.1.2" - mime "^2.4.6" - qs "^6.9.4" - readable-stream "^3.6.0" - semver "^7.3.2" - supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" From f8a4760ba33e7ac3231e713c60ea836fbd7747d3 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Mon, 7 Nov 2022 00:29:04 +0530 Subject: [PATCH 29/86] ABI method during app creation --- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 2 +- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 5 +- .../AppManager/CreateApp/CreateApp.tsx | 100 +++++++++++++++--- 3 files changed, 87 insertions(+), 20 deletions(-) diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 8000a583..24fd4a29 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -72,7 +72,7 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support setState(prevState => ({...prevState, showCreateApp: true})); }} >Create App - {setState(prevState => ({...prevState, showCreateApp: false}));}}> + {setState(prevState => ({...prevState, showCreateApp: false}));}}>
: ''}
diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index c26bbf5a..101a9d84 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -76,8 +76,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth {appId, signer, executorArgs}, setState ] = useState({ - ...initialState, - appId: new ABIConfig().getAppId() + ...initialState }); @@ -103,7 +102,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth ...arg, value: '' }); - setState(prevState => ({...prevState, executorArgs: processedArgs})); + setState(prevState => ({...prevState, executorArgs: processedArgs, appId: new ABIConfig().getAppId()})); }); }, [show]); diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index acc248e6..b0cc8769 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -8,10 +8,10 @@ import { DialogTitle, FormLabel, Grid, IconButton, InputBase, - InputBaseProps, - styled, TextField, Tooltip + InputBaseProps, MenuItem, Select, + styled } from "@mui/material"; -import {CancelOutlined, CloudUpload, CloudUploadOutlined, FileUploadOutlined} from "@mui/icons-material"; +import {CancelOutlined, FileUploadOutlined} from "@mui/icons-material"; import {theme} from "../../../../theme"; import {useDispatch} from "react-redux"; import {getFileContent} from "../../../../packages/core-sdk/utils/fileUtils"; @@ -19,8 +19,9 @@ import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import {handleException} from "../../../../redux/common/actions/exception"; import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicationClient"; import dappflow from "../../../../utils/dappflow"; -import {ApplicationParams, CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; -import {TransactionApplication} from "algosdk/dist/types/src/client/v2/indexer/models/types"; +import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; +import {ABIContract, ABIContractParams, getMethodByName} from "algosdk"; +import {ABIMethodParams} from "algosdk/dist/types/src/abi/method"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -42,7 +43,8 @@ const formLabelStyle = { interface CreateAppProps{ show: boolean, - handleClose?: Function + handleClose?: Function, + abi?: ABIContractParams, } const defaultProps: CreateAppProps = { @@ -56,7 +58,10 @@ interface CreateAppState{ clearProgram: string, globalBytes: string, localBytes: string, - } + globalInts: string, + localInts: string, + }, + abiMethod: ABIMethodParams } const initialState: CreateAppState = { @@ -65,17 +70,28 @@ const initialState: CreateAppState = { approvalProgram: '', clearProgram: '', globalBytes: '', - localBytes: '' + localBytes: '', + globalInts: '', + localInts: '' }, + abiMethod: { + name: '', + desc: '', + args: [], + returns: { + type: '', + desc: '' + } + } }; -function CreateApp({show = defaultProps.show, handleClose}: CreateAppProps): JSX.Element { +function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], name: ""}}: CreateAppProps): JSX.Element { const dispatch = useDispatch(); const [ - {params}, + {params, abiMethod}, setState ] = useState({ ...initialState @@ -120,7 +136,7 @@ function CreateApp({show = defaultProps.show, handleClose}: CreateAppProps): JSX {show ? @@ -142,7 +158,7 @@ function CreateApp({show = defaultProps.show, handleClose}: CreateAppProps): JSX
- + Global bytes - + + Global ints + { + setState(prevState => ({...prevState, params: { + ...params, + globalInts: ev.target.value + }})); + } + } + fullWidth/> + + Local bytes - + + Local ints + { + setState(prevState => ({...prevState, params: { + ...params, + localInts: ev.target.value + }})); + } + } + fullWidth/> + + Approval program
- - - +
diff --git a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx index b104e205..afbb282a 100644 --- a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx +++ b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx @@ -1,14 +1,12 @@ import './KMDConfiguration.scss'; import {useDispatch} from "react-redux"; import React, {useState} from "react"; -import {CancelOutlined} from "@mui/icons-material"; import { Button, Dialog, DialogActions, DialogContent, DialogTitle, FormLabel, Grid, - IconButton, InputBase, InputBaseProps, styled } from "@mui/material"; import {theme} from "../../../theme"; @@ -19,6 +17,7 @@ import {hideLoader, showLoader} from "../../../redux/common/actions/loader"; import {isBrave} from "../../../packages/core-sdk/utils"; import {KMDConnectionParams} from "../../../packages/core-sdk/types"; import {KmdClient} from "../../../packages/core-sdk/clients/kmdClient"; +import CloseIcon from "@mui/icons-material/Close"; const kmdConfig = getKMDConfig(); @@ -136,9 +135,7 @@ function KMDConfiguration(props): JSX.Element {
KMD Configuration
- - - +
diff --git a/src/components/LeftBar/Settings/Settings.tsx b/src/components/LeftBar/Settings/Settings.tsx index 36a0da3e..d20199b8 100644 --- a/src/components/LeftBar/Settings/Settings.tsx +++ b/src/components/LeftBar/Settings/Settings.tsx @@ -4,14 +4,12 @@ import {useDispatch, useSelector} from "react-redux"; import {RootState} from "../../../redux/store"; import React, {useState} from "react"; import {hideSettings} from "../../../redux/settings/actions/settings"; -import {CancelOutlined} from "@mui/icons-material"; import { Button, Chip, Dialog, DialogActions, DialogContent, DialogTitle, FormLabel, Grid, - IconButton, InputBase, InputBaseProps, styled, Typography } from "@mui/material"; import {theme} from "../../../theme"; @@ -22,6 +20,7 @@ import {Network} from "../../../packages/core-sdk/network"; import {hideLoader, showLoader} from "../../../redux/common/actions/loader"; import {isBrave} from "../../../packages/core-sdk/utils"; import {NodeConnectionParams} from "../../../packages/core-sdk/types"; +import CloseIcon from '@mui/icons-material/Close'; const nodeConfig = getNodeConfig(); @@ -176,9 +175,7 @@ function Settings(): JSX.Element {
Node Settings
- - - +
diff --git a/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx index 2c0a2175..0fa697d4 100644 --- a/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx +++ b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx @@ -6,12 +6,10 @@ import { DialogActions, DialogContent, DialogTitle, FormLabel, - IconButton, InputBase, InputBaseProps, styled } from "@mui/material"; -import {CancelOutlined} from "@mui/icons-material"; import {theme} from "../../../../theme"; import {useDispatch} from "react-redux"; import {showSnack} from "../../../../redux/common/actions/snackbar"; @@ -21,6 +19,7 @@ import dappflow from "../../../../utils/dappflow"; import {handleException} from "../../../../redux/common/actions/exception"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import ABIConfigCls from '../../../../packages/abi/classes/ABIConfig'; +import CloseIcon from "@mui/icons-material/Close"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -89,9 +88,7 @@ function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX
ABI Config
- - - +
diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 101a9d84..b78d16f2 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -11,10 +11,8 @@ import { DialogActions, DialogContent, DialogTitle, FormLabel, - Grid, - IconButton, InputBase, InputBaseProps, styled + Grid, InputBase, InputBaseProps, styled } from "@mui/material"; -import {CancelOutlined} from "@mui/icons-material"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {theme} from "../../../../theme"; import {useDispatch, useSelector} from "react-redux"; @@ -26,6 +24,7 @@ import {showSnack} from "../../../../redux/common/actions/snackbar"; import {handleException} from "../../../../redux/common/actions/exception"; import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; import {A_ABI_METHOD_EXECUTOR_ARG} from "../../../../packages/abi/types"; +import CloseIcon from "@mui/icons-material/Close"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -175,9 +174,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
Execute ABI Method
- - - +
diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.tsx b/src/components/Modules/ABI/ImportABI/ImportABI.tsx index bdee6d11..32cd3767 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.tsx +++ b/src/components/Modules/ABI/ImportABI/ImportABI.tsx @@ -5,10 +5,8 @@ import { Dialog, DialogActions, DialogContent, - DialogTitle, FormLabel, - IconButton, InputBase, InputBaseProps, styled, Tab, Tabs, Typography + DialogTitle, FormLabel, InputBase, InputBaseProps, styled, Tab, Tabs, Typography } from "@mui/material"; -import {CancelOutlined} from "@mui/icons-material"; import FileUploadIcon from '@mui/icons-material/FileUpload'; import {useDispatch} from "react-redux"; import {showSnack} from "../../../../redux/common/actions/snackbar"; @@ -17,6 +15,7 @@ import {handleException} from "../../../../redux/common/actions/exception"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import {ABIContract} from "algosdk"; import {theme} from "../../../../theme"; +import CloseIcon from "@mui/icons-material/Close"; export const ShadedInput = styled(InputBase)(({ theme }) => { @@ -72,9 +71,7 @@ function ImportABI(props): JSX.Element {
Import ABI
- - - +
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index b0cc8769..204aee2d 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -6,12 +6,11 @@ import { DialogActions, DialogContent, DialogTitle, FormLabel, Grid, - IconButton, InputBase, InputBaseProps, MenuItem, Select, styled } from "@mui/material"; -import {CancelOutlined, FileUploadOutlined} from "@mui/icons-material"; +import {FileUploadOutlined} from "@mui/icons-material"; import {theme} from "../../../../theme"; import {useDispatch} from "react-redux"; import {getFileContent} from "../../../../packages/core-sdk/utils/fileUtils"; @@ -22,6 +21,7 @@ import dappflow from "../../../../utils/dappflow"; import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; import {ABIContract, ABIContractParams, getMethodByName} from "algosdk"; import {ABIMethodParams} from "algosdk/dist/types/src/abi/method"; +import CloseIcon from "@mui/icons-material/Close"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -145,9 +145,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n
Create Application
- - - +
diff --git a/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx b/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx index 58137ebc..946c7fb9 100644 --- a/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx +++ b/src/components/Modules/Explorer/Records/Asset/Actions/AssetARCValidator/AssetARCValidator.tsx @@ -1,7 +1,6 @@ import './AssetARCValidator.scss'; import React, {useState} from "react"; -import {Button, Dialog, DialogActions, DialogContent, DialogTitle, IconButton} from "@mui/material"; -import {CancelOutlined} from "@mui/icons-material"; +import {Button, Dialog, DialogActions, DialogContent, DialogTitle} from "@mui/material"; import {ARC3} from "../../../../../../../packages/arc-portal/classes/ARC3/ARC3"; import {ARC19} from "../../../../../../../packages/arc-portal/classes/ARC19/ARC19"; import {ARC69} from "../../../../../../../packages/arc-portal/classes/ARC69/ARC69"; @@ -12,6 +11,7 @@ import CancelIcon from '@mui/icons-material/Cancel'; import { CircularProgress } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; interface AssetArcValidatorState{ show: boolean, @@ -110,9 +110,7 @@ function AssetARCValidator(props): JSX.Element {
ARC Validator
- - - +
diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx index 4ea4db2b..dfa9e574 100644 --- a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnInnerTxns/AppCallTxnInnerTxns.tsx @@ -9,18 +9,18 @@ import SvgIcon, {SvgIconProps} from '@mui/material/SvgIcon'; import { alpha, styled } from '@mui/material/styles'; import TreeView from '@mui/lab/TreeView'; import TreeItem, {treeItemClasses } from '@mui/lab/TreeItem'; -import {ArrowForward, CancelOutlined} from "@mui/icons-material"; +import {ArrowForward} from "@mui/icons-material"; import { Chip, Dialog, DialogActions, DialogContent, - DialogTitle, - IconButton + DialogTitle } from "@mui/material"; import InnerTransaction from "../../../../InnerTransaction/InnerTransaction"; import {AssetClient} from "../../../../../../../../../packages/core-sdk/clients/assetClient"; import explorer from "../../../../../../../../../utils/dappflow"; +import CloseIcon from "@mui/icons-material/Close"; export function MinusSquare(props: SvgIconProps) { return ( @@ -183,9 +183,7 @@ function AppCallTxnInnerTxns(props): JSX.Element {
 
- - - +
diff --git a/src/components/Modules/Explorer/Search/Search.tsx b/src/components/Modules/Explorer/Search/Search.tsx index 5d9928b6..228997ab 100644 --- a/src/components/Modules/Explorer/Search/Search.tsx +++ b/src/components/Modules/Explorer/Search/Search.tsx @@ -9,7 +9,7 @@ import { IconButton, InputBase } from "@mui/material"; -import {CancelOutlined, Search as SearchIcon} from "@mui/icons-material"; +import {Search as SearchIcon} from "@mui/icons-material"; import {isValidAddress} from "algosdk"; import {useNavigate} from "react-router-dom"; import {A_Application, A_Asset, A_Block} from "../../../../packages/core-sdk/types"; @@ -22,6 +22,7 @@ import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import {useDispatch} from "react-redux"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {theme} from "../../../../theme"; +import CloseIcon from "@mui/icons-material/Close"; interface searchResult { @@ -185,9 +186,7 @@ function Search(): JSX.Element {
Search results
- - - +
diff --git a/src/index.scss b/src/index.scss index 341efd58..c9f9fa20 100644 --- a/src/index.scss +++ b/src/index.scss @@ -31,3 +31,9 @@ body { * { font-family: "Poppins" !important; } + +.modal-close-button { + &:hover { + cursor: pointer; + } +} \ No newline at end of file From edd9db675923442a0601d23736c8aa8eb9d0a06f Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Mon, 7 Nov 2022 23:38:20 +0530 Subject: [PATCH 31/86] forms styling --- .../KMDConfiguration/KMDConfiguration.tsx | 15 +++-- src/components/LeftBar/Settings/Settings.tsx | 19 ++++-- .../Modules/Dispenser/Dispenser.tsx | 64 ++++++++++--------- 3 files changed, 54 insertions(+), 44 deletions(-) diff --git a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx index afbb282a..9044823f 100644 --- a/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx +++ b/src/components/LeftBar/KMDConfiguration/KMDConfiguration.tsx @@ -30,6 +30,12 @@ const ShadedInput = styled(InputBase)(({ theme }) => { }; }); +const formLabelStyle = { + marginLeft: '5px', + fontSize: '14px', + fontWeight: 'bold', + color: theme.palette.grey[600] +}; interface KMDConfigurationState{ url: string, @@ -47,9 +53,6 @@ function KMDConfiguration(props): JSX.Element { const dispatch = useDispatch(); const show = props.show ? true : false; - const primaryClr = theme.palette.primary.main; - - const [ {url, port, token}, @@ -146,7 +149,7 @@ function KMDConfiguration(props): JSX.Element {
- KMD url + KMD url - KMD port + KMD port - KMD token + KMD token (({ theme }) => { }; }); +const formLabelStyle = { + marginLeft: '5px', + fontSize: '14px', + fontWeight: 'bold', + color: theme.palette.grey[600] +}; interface SettingsState{ algodUrl: string, @@ -57,7 +63,6 @@ function Settings(): JSX.Element { const dispatch = useDispatch(); const settings = useSelector((state: RootState) => state.settings); const {show} = settings; - const primaryClr = theme.palette.primary.main; const nodes = getNodes(); @@ -210,7 +215,7 @@ function Settings(): JSX.Element {
- Algod url + Algod url - Algod port + Algod port - Algod token + Algod token - Indexer url + Indexer url - Indexer port + Indexer port - Indexer token + Indexer token (({ theme }) => { + return { + padding: 5, + paddingLeft: 10, + marginTop: 5, + border: '1px solid ' + theme.palette.grey[200] + }; +}); + +const formLabelStyle = { + marginLeft: '5px', + color: theme.palette.grey[600] +}; interface DispenserState{ address: string, @@ -146,7 +159,7 @@ function Dispenser(): JSX.Element {
{isSandbox ? +
- } - } - >Save
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 204aee2d..7e93eb0e 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -7,7 +7,7 @@ import { DialogContent, DialogTitle, FormLabel, Grid, InputBase, - InputBaseProps, MenuItem, Select, + InputBaseProps, styled } from "@mui/material"; import {FileUploadOutlined} from "@mui/icons-material"; @@ -19,7 +19,7 @@ import {handleException} from "../../../../redux/common/actions/exception"; import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicationClient"; import dappflow from "../../../../utils/dappflow"; import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; -import {ABIContract, ABIContractParams, getMethodByName} from "algosdk"; +import {ABIContractParams} from "algosdk"; import {ABIMethodParams} from "algosdk/dist/types/src/abi/method"; import CloseIcon from "@mui/icons-material/Close"; @@ -60,6 +60,7 @@ interface CreateAppState{ localBytes: string, globalInts: string, localInts: string, + note: string }, abiMethod: ABIMethodParams } @@ -72,7 +73,8 @@ const initialState: CreateAppState = { globalBytes: '', localBytes: '', globalInts: '', - localInts: '' + localInts: '', + note: '' }, abiMethod: { name: '', @@ -91,7 +93,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n const dispatch = useDispatch(); const [ - {params, abiMethod}, + {params}, setState ] = useState({ ...initialState @@ -218,9 +220,8 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n + + + >Create + +
From a3ee115f660e32e62d1c3d8824ae302b95b4504a Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 8 Nov 2022 15:15:58 +0530 Subject: [PATCH 33/86] prepare app creation transaction api --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 46 +--------- .../AppManager/CreateApp/CreateApp.tsx | 91 ++++++++++++++++++- src/packages/abi/classes/ABIMethodExecutor.ts | 23 +---- .../core-sdk/clients/transactionClient.ts | 11 +-- .../transactions/applicationTransaction.ts | 18 ++++ .../core-sdk/transactions/baseTransaction.ts | 29 ++++++ src/packages/core-sdk/types.ts | 17 +++- src/packages/core-sdk/utils.ts | 2 +- 8 files changed, 160 insertions(+), 77 deletions(-) create mode 100644 src/packages/core-sdk/transactions/applicationTransaction.ts create mode 100644 src/packages/core-sdk/transactions/baseTransaction.ts diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index b78d16f2..bfc47ece 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -2,8 +2,7 @@ import './ABIMethodExecutor.scss'; import React, {useEffect, useState} from "react"; import { ABIMethod, - ABIMethodParams, - mnemonicToSecretKey + ABIMethodParams } from "algosdk"; import { Button, @@ -15,11 +14,8 @@ import { } from "@mui/material"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {theme} from "../../../../theme"; -import {useDispatch, useSelector} from "react-redux"; -import {RootState} from "../../../../redux/store"; +import {useDispatch} from "react-redux"; import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; -import {CoreNode} from "../../../../packages/core-sdk/classes/core/CoreNode"; -import {ellipseString} from "../../../../packages/core-sdk/utils"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {handleException} from "../../../../redux/common/actions/exception"; import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; @@ -58,13 +54,11 @@ const defaultProps: ABIMethodExecutorProps = { interface ABIMethodExecutorState{ appId: string, - signer: string, executorArgs: A_ABI_METHOD_EXECUTOR_ARG[] } const initialState: ABIMethodExecutorState = { appId: '', - signer: '', executorArgs: [] }; @@ -72,7 +66,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const dispatch = useDispatch(); const [ - {appId, signer, executorArgs}, + {appId, executorArgs}, setState ] = useState({ ...initialState @@ -83,13 +77,6 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const args = abiMethodInstance.args; - - const node = useSelector((state: RootState) => state.node); - const {status, versionsCheck, genesis, health} = node; - const kmd = useSelector((state: RootState) => state.kmd); - const {mnemonics} = kmd; - - const clearState = () => { setState({ ...initialState }); }; @@ -106,18 +93,6 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth }, [show]); - useEffect(() => { - const isSandbox = new CoreNode(status, versionsCheck, genesis, health).isSandbox(); - if (isSandbox) { - if (mnemonics.length > 0) { - const accounts = mnemonics.map((mnemonic) => { - return mnemonicToSecretKey(mnemonic); - }) - setState(prevState => ({...prevState, signer: accounts[0].addr})); - } - } - }, [show, status, versionsCheck, genesis, health]); - function onClose(ev) { handleClose(); @@ -134,19 +109,11 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth })); return; } - if (!signer) { - dispatch(showSnack({ - severity: 'error', - message: 'Invalid Signer.' - })); - return; - } try { const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); - const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), signer, executorArgs); - const signedTxns = await abiMethodExecutorInstance.signMethodTxns(unsignedTxns, mnemonicToSecretKey(mnemonics[0])); - await abiMethodExecutorInstance.execute(signedTxns); + const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), 'CESUKTCKPQZQJ2ZOP5K6M6557S327ZNIWYSIGD7BMLAPFWDJDQWFCHZNMI', executorArgs); + console.log(unsignedTxns); } catch (e: any) { dispatch(handleException(e)); @@ -196,9 +163,6 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
Application ID : {appId}
-
- Signer : {signer ? ellipseString(signer, 30) : ''} -
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 7e93eb0e..08d91712 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -22,6 +22,9 @@ import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/typ import {ABIContractParams} from "algosdk"; import {ABIMethodParams} from "algosdk/dist/types/src/abi/method"; import CloseIcon from "@mui/icons-material/Close"; +import {showSnack} from "../../../../redux/common/actions/snackbar"; +import {isNumber} from "../../../../utils/common"; +import {ApplicationTransaction} from "../../../../packages/core-sdk/transactions/applicationTransaction"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -121,7 +124,6 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n dispatch(showLoader('Compiling program')); const compileResp = await new ApplicationClient(dappflow.network).compileProgram(content); dispatch(hideLoader()); - console.log(compileResp); target.value = null; return compileResp; @@ -132,6 +134,89 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n } } + async function create() { + const {globalBytes, globalInts, localBytes, localInts, approvalProgram, clearProgram, note} = params; + if (!globalBytes || !isNumber(globalBytes)) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid global bytes' + })); + return; + } + if (!globalInts || !isNumber(globalInts)) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid global ints' + })); + return; + } + if (!localBytes || !isNumber(localBytes)) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid local bytes' + })); + return; + } + if (!localInts || !isNumber(localInts)) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid local ints' + })); + return; + } + if (!approvalProgram) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid approval program' + })); + return; + } + if (!clearProgram) { + dispatch(showSnack({ + severity: 'error', + message: 'Invalid clear program' + })); + return; + } + + try { + const txnInstance = new ApplicationTransaction(dappflow.network); + const unsignedTxn = await txnInstance.prepareCreateTxn({ + appApprovalProgram: txnInstance.toUint8Array(approvalProgram), + appArgs: [], + appClearProgram: txnInstance.toUint8Array(clearProgram), + appForeignApps: [], + appForeignAssets: [], + appGlobalByteSlices: Number(globalBytes), + appGlobalInts: Number(globalInts), + appIndex: 0, + appLocalByteSlices: Number(localBytes), + appLocalInts: Number(localInts), + appOnComplete: undefined, + boxes: [], + extraPages: 0, + fee: 0, + firstRound: 0, + flatFee: false, + from: "CESUKTCKPQZQJ2ZOP5K6M6557S327ZNIWYSIGD7BMLAPFWDJDQWFCHZNMI", + genesisHash: "", + genesisID: "", + lastRound: 0, + lease: undefined, + reKeyTo: "", + suggestedParams: undefined, + type: undefined, + appAccounts: [], + note: txnInstance.toUint8Array(note) + }); + + console.log(unsignedTxn); + } + catch (e: any) { + dispatch(handleException(e)); + } + } + return (
@@ -328,9 +413,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index b896681e..b9161d58 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -3,13 +3,12 @@ import { ABIMethod, ABIMethodParams, ABITransactionType, - abiTypeIsTransaction, Account, + abiTypeIsTransaction, AtomicTransactionComposer, TransactionWithSigner } from "algosdk"; import {A_ABI_METHOD_EXECUTOR_ARG, ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; -import {TransactionClient} from "../../core-sdk/clients/transactionClient"; import dappflow from "../../../utils/dappflow"; -import {WalletSigner} from "../../signers"; +import {BaseTransaction} from "../../core-sdk/transactions/baseTransaction"; export default class ABIMethodExecutor { method: ABIMethodParams @@ -79,7 +78,7 @@ export default class ABIMethodExecutor { async getUnsignedTxns(appId: number, from: string, args: A_ABI_METHOD_EXECUTOR_ARG[] = []): Promise { const atc = new AtomicTransactionComposer(); - const sp = await new TransactionClient(dappflow.network).getSuggestedParams(); + const sp = await new BaseTransaction(dappflow.network).getSuggestedParams(); const appCallParams = { appID: appId, @@ -101,20 +100,4 @@ export default class ABIMethodExecutor { const unsignedTxns= atc.buildGroup(); return unsignedTxns; } - - async signMethodTxns(unsignedTxns: TransactionWithSigner[], account: Account): Promise { - const signer = new WalletSigner(account); - const txns = []; - unsignedTxns.forEach((unsignedTxn) => { - txns.push(unsignedTxn.txn); - }); - const signedTxns = signer.signGroupTxns(txns); - return signedTxns - } - - async execute(signedTxns: Uint8Array[]) { - const txnClient = new TransactionClient(dappflow.network); - const resp = await txnClient.send(signedTxns); - console.log(resp); - } } \ No newline at end of file diff --git a/src/packages/core-sdk/clients/transactionClient.ts b/src/packages/core-sdk/clients/transactionClient.ts index 5c0b250d..8795adff 100644 --- a/src/packages/core-sdk/clients/transactionClient.ts +++ b/src/packages/core-sdk/clients/transactionClient.ts @@ -1,4 +1,4 @@ -import {Algodv2, SuggestedParams} from "algosdk"; +import {Algodv2} from "algosdk"; import IndexerClient from "algosdk/dist/types/src/client/v2/indexer/indexer"; import {Network} from "../network"; import {A_SearchTransaction} from "../types"; @@ -34,13 +34,4 @@ export class TransactionClient { const {transactions} = await this.indexer.searchForTransactions().txid(id).do(); return transactions[0]; } - - async getSuggestedParams(): Promise{ - const sp = await this.client.getTransactionParams().do(); - return sp; - } - - async send(txns: Uint8Array | Uint8Array[]): Promise { - return await this.client.sendRawTransaction(txns).do(); - } } \ No newline at end of file diff --git a/src/packages/core-sdk/transactions/applicationTransaction.ts b/src/packages/core-sdk/transactions/applicationTransaction.ts new file mode 100644 index 00000000..28842a14 --- /dev/null +++ b/src/packages/core-sdk/transactions/applicationTransaction.ts @@ -0,0 +1,18 @@ +import sdk, {Transaction} from 'algosdk'; +import {BaseTransaction} from "./baseTransaction"; +import {Network} from "../network"; +import {AppCreateTxn} from "algosdk"; + +export class ApplicationTransaction extends BaseTransaction{ + + // eslint-disable-next-line @typescript-eslint/no-useless-constructor + constructor(network: Network) { + super(network); + } + + async prepareCreateTxn(params: AppCreateTxn): Promise { + const suggestedParams = await this.getSuggestedParams(); + const {from, appOnComplete, appApprovalProgram, appClearProgram, appLocalByteSlices, appLocalInts, appGlobalByteSlices, appGlobalInts, appArgs, appForeignApps, appForeignAssets, appAccounts, note} = params; + return sdk.makeApplicationCreateTxn(from, suggestedParams, appOnComplete, appApprovalProgram, appClearProgram, appLocalInts, appLocalByteSlices, appGlobalInts, appGlobalByteSlices, appArgs, appAccounts, appForeignApps, appForeignAssets, note); + } +} \ No newline at end of file diff --git a/src/packages/core-sdk/transactions/baseTransaction.ts b/src/packages/core-sdk/transactions/baseTransaction.ts new file mode 100644 index 00000000..db140398 --- /dev/null +++ b/src/packages/core-sdk/transactions/baseTransaction.ts @@ -0,0 +1,29 @@ +import {Algodv2, SuggestedParams} from "algosdk"; +import IndexerClient from "algosdk/dist/types/src/client/v2/indexer/indexer"; +import {Network} from "../network"; + + +export class BaseTransaction { + client: Algodv2; + indexer: IndexerClient; + network: Network; + + constructor(network: Network) { + this.network = network; + this.client = network.getClient(); + this.indexer = network.getIndexer(); + } + + async getSuggestedParams(): Promise{ + return await this.client.getTransactionParams().do(); + } + + async send(txns: Uint8Array | Uint8Array[]): Promise { + return await this.client.sendRawTransaction(txns).do(); + } + + toUint8Array(text: string): Uint8Array { + const enc = new TextEncoder(); + return enc.encode(text); + } +} \ No newline at end of file diff --git a/src/packages/core-sdk/types.ts b/src/packages/core-sdk/types.ts index 810a9e10..90281881 100644 --- a/src/packages/core-sdk/types.ts +++ b/src/packages/core-sdk/types.ts @@ -1,4 +1,4 @@ -import {ABIMethodArgParams, ABIValue} from "algosdk"; +import {ABIMethodArgParams, ABIValue, OnApplicationComplete} from "algosdk"; import { AlgodTokenHeader, CustomTokenHeader, @@ -395,3 +395,18 @@ export type A_Genesis = { export type A_ABIMethodArgParams = ABIMethodArgParams & {value: string, decodedValue: ABIValue, decoded: boolean} +export interface A_CreateApplicationParams { + from: string + approvalProgram: Uint8Array + clearProgram: Uint8Array + localInts: number + localBytes: number + globalInts: number + globalBytes: number + onComplete: OnApplicationComplete + appArgs?: any[] + foreignAccounts?: string[] + foreignApps?: number[] + foreignAssets?: number[] +} + diff --git a/src/packages/core-sdk/utils.ts b/src/packages/core-sdk/utils.ts index c34f2b68..0f590fc8 100644 --- a/src/packages/core-sdk/utils.ts +++ b/src/packages/core-sdk/utils.ts @@ -8,4 +8,4 @@ export function ellipseString(str: string = "", width: number = 10): string { export function isBrave() { // @ts-ignore return navigator.brave && navigator.brave.isBrave(); -} \ No newline at end of file +} From c823798dd102790a1acf1258d86f23acce75449b Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 8 Nov 2022 15:33:20 +0530 Subject: [PATCH 34/86] foreign items for app creation --- .../AppManager/CreateApp/CreateApp.tsx | 74 +++++++++++++++++-- 1 file changed, 66 insertions(+), 8 deletions(-) diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 08d91712..a0b75854 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -63,7 +63,10 @@ interface CreateAppState{ localBytes: string, globalInts: string, localInts: string, - note: string + note: string, + foreignAssets: string, + foreignApps: string, + accounts: string }, abiMethod: ABIMethodParams } @@ -77,7 +80,10 @@ const initialState: CreateAppState = { localBytes: '', globalInts: '', localInts: '', - note: '' + note: '', + foreignApps: '', + foreignAssets: '', + accounts: '' }, abiMethod: { name: '', @@ -135,7 +141,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n } async function create() { - const {globalBytes, globalInts, localBytes, localInts, approvalProgram, clearProgram, note} = params; + const {globalBytes, globalInts, localBytes, localInts, approvalProgram, clearProgram, note, foreignAssets, foreignApps, accounts} = params; if (!globalBytes || !isNumber(globalBytes)) { dispatch(showSnack({ severity: 'error', @@ -185,8 +191,8 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n appApprovalProgram: txnInstance.toUint8Array(approvalProgram), appArgs: [], appClearProgram: txnInstance.toUint8Array(clearProgram), - appForeignApps: [], - appForeignAssets: [], + appForeignApps: foreignApps ? foreignApps.split(',').map(app => Number(app)): [], + appForeignAssets: foreignAssets ? foreignAssets.split(',').map(asset => Number(asset)): [], appGlobalByteSlices: Number(globalBytes), appGlobalInts: Number(globalInts), appIndex: 0, @@ -206,7 +212,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n reKeyTo: "", suggestedParams: undefined, type: undefined, - appAccounts: [], + appAccounts: accounts ? accounts.split(','): [], note: txnInstance.toUint8Array(note) }); @@ -359,11 +365,63 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n - + + + Foreign assets + { + setState(prevState => ({...prevState, params: { + ...params, + foreignAssets: ev.target.value + }})); + } + } + fullWidth/> + + + + Foreign apps + { + setState(prevState => ({...prevState, params: { + ...params, + foreignApps: ev.target.value + }})); + } + } + fullWidth/> + + + + Accounts + { + setState(prevState => ({...prevState, params: { + ...params, + accounts: ev.target.value + }})); + } + } + fullWidth/> + + + Note { From 0bad073948050111bf57108473b4151d26afb196 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 8 Nov 2022 18:40:37 +0530 Subject: [PATCH 35/86] left bar connect wallet button --- src/components/LeftBar/LeftBar.scss | 35 ++++++++++++++------ src/components/LeftBar/LeftBar.tsx | 51 +++++++++++++++-------------- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/components/LeftBar/LeftBar.scss b/src/components/LeftBar/LeftBar.scss index 8b7247cb..97664871 100644 --- a/src/components/LeftBar/LeftBar.scss +++ b/src/components/LeftBar/LeftBar.scss @@ -17,24 +17,39 @@ width: 100%; padding: 10px 0px; border-top: 1px solid $color-grey-light; - .node { - margin: 10px 0px; - &:hover { - cursor: pointer; - } - .node-url { + + .node-wrapper { + .node-container { text-align: center; - font-size: 13px; + margin-top: 20px; + border-top: 1px solid $color-grey-very-light; + padding: 15px 0; &:hover { cursor: pointer; } - svg { - margin-right: 5px; - vertical-align: sub; + .node { + color: $color-dark; + .node-url { + text-align: center; + font-size: 13px; + color: $color-dark; + svg { + margin-right: 5px; + } + } } } } + .connect-wallet-wrapper { + .connect-wallet-container { + text-align: center; + border-top: 1px solid $color-grey-very-light; + padding: 15px 0; + margin-bottom: -10px; + } + } + } .logo { height: 80px; diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index 9b7a4062..21213cb5 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -1,7 +1,7 @@ import './LeftBar.scss'; import { Box, - Button, Chip, Tab, Tabs + Button, Tab, Tabs } from "@mui/material"; import {useDispatch, useSelector} from "react-redux"; import React from "react"; @@ -10,15 +10,13 @@ import {showSettings} from "../../redux/settings/actions/settings"; import Logo from '../../assets/images/logo-black.png'; import {useLocation, useNavigate} from "react-router-dom"; import {RootState} from "../../redux/store"; -import {shadedClr, shadedClr1} from "../../utils/common"; +import {shadedClr, shadedClr1, shadedClr2} from "../../utils/common"; import CodeIcon from '@mui/icons-material/Code'; import StorageIcon from '@mui/icons-material/Storage'; import GavelIcon from '@mui/icons-material/Gavel'; import DeveloperBoardIcon from '@mui/icons-material/DeveloperBoard'; import ShowerIcon from '@mui/icons-material/Shower'; import InsertChartIcon from '@mui/icons-material/InsertChart'; -import CheckCircleIcon from '@mui/icons-material/CheckCircle'; -import SignalWifiConnectedNoInternet4Icon from '@mui/icons-material/SignalWifiConnectedNoInternet4'; import {CoreNode} from "../../packages/core-sdk/classes/core/CoreNode"; import {supportSettings} from "../../utils/nodeConfig"; @@ -92,41 +90,46 @@ function LeftBar(): JSX.Element {
- {supportSettings ? : ''} -
{ +
{ if (supportSettings) { dispatch(showSettings()); ev.stopPropagation(); ev.preventDefault(); } }}> +
+
- + - - {success ? - - Network : {new CoreNode(node.status, node.versionsCheck, node.genesis, node.health).getGenesisId()} +
+ + {success ? + {new CoreNode(node.status, node.versionsCheck, node.genesis, node.health).getGenesisId()} : - Unable to connect} +
-
}> - + +
+
+
+
+ +
+
+ +
From b5691b5518bdf33224f448606724e58aaf0e17a1 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 8 Nov 2022 22:31:24 +0530 Subject: [PATCH 36/86] wallet connect flow --- .../LeftBar/ConnectWallet/ConnectWallet.scss | 115 ++++++++++++ .../LeftBar/ConnectWallet/ConnectWallet.tsx | 168 ++++++++++++++++++ src/components/LeftBar/LeftBar.scss | 38 ++-- src/components/LeftBar/LeftBar.tsx | 13 +- src/packages/core-sdk/types.ts | 14 -- src/packages/signers/constants/index.ts | 12 -- src/redux/store.ts | 8 +- src/redux/wallet/actions/connectWallet.ts | 90 ++++++++++ src/redux/wallet/actions/signer.ts | 23 +++ src/redux/wallet/actions/wallet.ts | 66 +++++++ 10 files changed, 490 insertions(+), 57 deletions(-) create mode 100644 src/components/LeftBar/ConnectWallet/ConnectWallet.scss create mode 100644 src/components/LeftBar/ConnectWallet/ConnectWallet.tsx create mode 100644 src/redux/wallet/actions/connectWallet.ts create mode 100644 src/redux/wallet/actions/signer.ts create mode 100644 src/redux/wallet/actions/wallet.ts diff --git a/src/components/LeftBar/ConnectWallet/ConnectWallet.scss b/src/components/LeftBar/ConnectWallet/ConnectWallet.scss new file mode 100644 index 00000000..0d50fec9 --- /dev/null +++ b/src/components/LeftBar/ConnectWallet/ConnectWallet.scss @@ -0,0 +1,115 @@ +@import '../../../assets/colors'; + +.connect-wallet-wrapper { + .connect-wallet-container { + margin-bottom: 40px; + .wallet-connect-home-wrapper { + .wallet-connect-home-container { + .header { + margin-top: 20px; + text-align: center; + .text { + font-size: 18px; + font-weight: bold; + font-family: PoppinsBold !important; + svg { + vertical-align: sub; + margin-right: 5px; + } + } + } + .body { + margin-top: 40px; + .signer { + padding: 20px 50px; + img.logo { + vertical-align: middle; + margin-right: 15px; + height: 25px; + width: 25px; + border-radius: 50%; + } + .name { + vertical-align: sub; + font-size: 16px; + } + svg { + float: right; + } + &:hover { + cursor: pointer; + background: $color-grey-very-light; + } + } + } + .footer { + text-align: center; + margin-top: 50px; + margin-bottom: 20px; + padding: 0 25px; + } + } + } + + .accounts-wrapper { + .accounts-container { + .header { + font-size: 20px; + text-align: center; + .logo { + width: 30px; + height: 30px; + vertical-align: middle; + margin-right: 10px; + } + } + .body { + margin-top: 40px; + img.loading { + width: 40%; + } + .connecting { + text-align: center; + margin-top: 75px; + font-size: 20px; + color: #A9A9A9; + } + .error-message { + text-align: center; + margin-top: 40px; + color: $color-grey-dark; + padding: 0 40px; + line-height: 1.2; + svg { + font-size: 50px; + margin-bottom: 20px; + margin-top: 50px; + } + img { + width: 170px; + height: 140px; + margin-bottom: 20px; + } + } + .account { + font-size: 14px; + font-weight: bold; + overflow-wrap: anywhere; + margin: 15px 40px; + background: #D7F7E2; + color: $color-dark; + padding: 15px; + border-radius: 10px; + line-height: 1.4; + &:hover { + background: linear-gradient(249.61deg, #60DD8B -8.07%, #0BB68C 99.24%); + cursor: pointer; + color: $color-light; + } + } + } + } + } + + } +} \ No newline at end of file diff --git a/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx b/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx new file mode 100644 index 00000000..c1475a7d --- /dev/null +++ b/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx @@ -0,0 +1,168 @@ +import './ConnectWallet.scss'; +import { + Dialog, DialogActions, + DialogContent, + DialogTitle, Typography, Button +} from "@mui/material"; +import {useDispatch, useSelector} from "react-redux"; +import React, {useEffect, useState} from "react"; +import {getSupportedSigners, SupportedSigner} from '../../../packages/signers'; +import {RootState} from "../../../redux/store"; +import {connect, hideConnectWallet} from "../../../redux/wallet/actions/connectWallet"; +import {loadWallet} from "../../../redux/wallet/actions/wallet"; +import {ArrowBack, ErrorOutlineOutlined} from "@mui/icons-material"; +import CloseIcon from "@mui/icons-material/Close"; +import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; +import PowerIcon from '@mui/icons-material/Power'; + + +interface ConnectWalletState{ + view: string, + selectedSigner: SupportedSigner +} + +const signers = getSupportedSigners(); + +const initialState: ConnectWalletState = { + view: "home", + selectedSigner: signers[0] +}; + +function ConnectWallet(): JSX.Element { + + const dispatch = useDispatch(); + + const connectWallet = useSelector((state: RootState) => state.connectWallet); + const {accounts} = connectWallet; + + const [ + { view, selectedSigner }, + setState + ] = useState(initialState); + + const clearState = () => { + setState({ ...initialState }); + }; + + useEffect(() => { + if (accounts.length === 1) { + clearState(); + } + }, [accounts]); + + return (
+ {connectWallet.show ? + +
+
+ {view === 'accounts' ? { + setState(prevState => ({ ...prevState, view: 'home' })); + }}/> : ''} + +
+ { + dispatch(hideConnectWallet()); + clearState(); + }}/> +
+
+ +
+
+ {view === 'home' ?
+
+
+ +
+ + Connect wallet +
+
+
+ {signers.map((signer) => { + return (
{ + dispatch(connect(signer)); + setState(prevState => ({ ...prevState, view: 'accounts', selectedSigner: signer })); + }} + > + {signer.logo ? logo : ''} + {signer.label} + +
); + })} +
+
+ + By connecting, You accept Dappflow Terms of Service + +
+
+
: ''} + + {view === 'accounts' ?
+
+
+ + {selectedSigner.logo ? logo : ''} + + + {selectedSigner.label} + +
+
+ {connectWallet.connecting ?
+
connecting ...
+
: ''} + {!connectWallet.connecting && connectWallet.errMessage ?
+ +
+ {connectWallet.errMessage} +
+ +
: ''} + {!connectWallet.connecting && accounts.length === 0 && !connectWallet.errMessage?
+
+ No accounts found +
+
: ''} + {accounts.map((account) => { + return (
{ + const address = account.address; + await dispatch(loadWallet(address)); + dispatch(hideConnectWallet()); + localStorage.setItem("signer", selectedSigner.name); + localStorage.setItem("address", address); + clearState(); + }}> + {account.address} +
); + })} +
+
+
: ''} +
+
+
+ + + +
: ''} +
); +} + +export default ConnectWallet; diff --git a/src/components/LeftBar/LeftBar.scss b/src/components/LeftBar/LeftBar.scss index 97664871..2742a03e 100644 --- a/src/components/LeftBar/LeftBar.scss +++ b/src/components/LeftBar/LeftBar.scss @@ -13,40 +13,28 @@ position: relative; .footer { position: absolute; - bottom: 0px; + bottom: 0; width: 100%; - padding: 10px 0px; - border-top: 1px solid $color-grey-light; - .node-wrapper { - .node-container { + .node { + color: $color-dark; + .node-url { text-align: center; - margin-top: 20px; - border-top: 1px solid $color-grey-very-light; - padding: 15px 0; - &:hover { - cursor: pointer; - } - .node { - color: $color-dark; - .node-url { - text-align: center; - font-size: 13px; - color: $color-dark; - svg { - margin-right: 5px; - } - } + font-size: 13px; + color: $color-dark; + svg { + margin-right: 5px; } } } - .connect-wallet-wrapper { - .connect-wallet-container { + .bottom-menu-item-wrapper { + .bottom-menu-item-container { text-align: center; - border-top: 1px solid $color-grey-very-light; padding: 15px 0; - margin-bottom: -10px; + &:hover { + cursor: pointer; + } } } diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index 21213cb5..9896dd0f 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -19,6 +19,8 @@ import ShowerIcon from '@mui/icons-material/Shower'; import InsertChartIcon from '@mui/icons-material/InsertChart'; import {CoreNode} from "../../packages/core-sdk/classes/core/CoreNode"; import {supportSettings} from "../../utils/nodeConfig"; +import {showConnectWallet} from "../../redux/wallet/actions/connectWallet"; +import ConnectWallet from "./ConnectWallet/ConnectWallet"; function LeftBar(): JSX.Element { @@ -92,14 +94,14 @@ function LeftBar(): JSX.Element { -
{ +
{ if (supportSettings) { dispatch(showSettings()); ev.stopPropagation(); ev.preventDefault(); } }}> -
+
@@ -117,15 +119,16 @@ function LeftBar(): JSX.Element {
-
-
+
+
+
diff --git a/src/packages/core-sdk/types.ts b/src/packages/core-sdk/types.ts index 90281881..fe2356a6 100644 --- a/src/packages/core-sdk/types.ts +++ b/src/packages/core-sdk/types.ts @@ -395,18 +395,4 @@ export type A_Genesis = { export type A_ABIMethodArgParams = ABIMethodArgParams & {value: string, decodedValue: ABIValue, decoded: boolean} -export interface A_CreateApplicationParams { - from: string - approvalProgram: Uint8Array - clearProgram: Uint8Array - localInts: number - localBytes: number - globalInts: number - globalBytes: number - onComplete: OnApplicationComplete - appArgs?: any[] - foreignAccounts?: string[] - foreignApps?: number[] - foreignAssets?: number[] -} diff --git a/src/packages/signers/constants/index.ts b/src/packages/signers/constants/index.ts index 8432223b..beb6a871 100644 --- a/src/packages/signers/constants/index.ts +++ b/src/packages/signers/constants/index.ts @@ -16,15 +16,3 @@ export enum ALGO_SIGNER_NET { TESTNET = 'TestNet', MAINNET = 'MainNet' } - -export enum LOCAL_STORAGE { - NETWORK = 'network' -} - -export const BURN_ADDRESS_MIN_BAL: number = 0.2; - -export enum NFT_STANDARDS { - ARC3 = "arc3", - ARC69 = 'arc69', -} -export const IPFS_GATEWAY = 'https://ipfs.io/ipfs'; \ No newline at end of file diff --git a/src/redux/store.ts b/src/redux/store.ts index a72a02fb..a8d572e9 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -19,6 +19,9 @@ import arc from "./arcPortal/actions/arc"; import node from "./network/actions/node"; import app from "./app/actions/app"; import kmd from "./explorer/actions/kmd"; +import connectWallet from "./wallet/actions/connectWallet"; +import wallet from "./wallet/actions/wallet"; +import signer from "./wallet/actions/signer"; export const store = configureStore({ reducer: { @@ -41,7 +44,10 @@ export const store = configureStore({ arc: arc, node: node, app: app, - kmd: kmd + kmd: kmd, + connectWallet: connectWallet, + wallet: wallet, + signer: signer }, }); diff --git a/src/redux/wallet/actions/connectWallet.ts b/src/redux/wallet/actions/connectWallet.ts new file mode 100644 index 00000000..1aa32284 --- /dev/null +++ b/src/redux/wallet/actions/connectWallet.ts @@ -0,0 +1,90 @@ +import {createAsyncThunk, createSlice, PayloadAction} from '@reduxjs/toolkit' +import {SignerAccount} from "../../../packages/signers/types"; +import {SupportedSigner} from "../../../packages/signers"; +import {setSigner} from "./signer"; +import {loadWallet} from "./wallet"; + + +export interface ConnectWallet { + show: boolean, + connecting: boolean, + errMessage: string, + accounts: SignerAccount[] +} + +const initialState: ConnectWallet = { + show: false, + connecting: false, + errMessage: "", + accounts: [] +} + +export const connect = createAsyncThunk( + 'connectWallet/connect', + async (signer: SupportedSigner, thunkAPI) => { + const {dispatch, getState} = thunkAPI; + try { + console.log(signer); + const appState: any = getState(); + const {network} = appState; + dispatch(walletConnecting()); + dispatch(clearAccounts()); + dispatch(setSigner(signer.name)); + + // @ts-ignore + const accounts = await signer.instance.connect(network.name, (err, payload)=> { + dispatch(walletConnected()); + dispatch(setErrorMessage(payload.params[0].message)); + }); + if (accounts.length === 1) { + dispatch(loadWallet(accounts[0].address)); + dispatch(hideConnectWallet()); + localStorage.setItem("signer", signer.name); + localStorage.setItem("address", accounts[0].address); + } + dispatch(walletConnected()); + return accounts; + } + catch (e: any) { + dispatch(walletConnected()); + dispatch(setErrorMessage(e.message)); + } + } +); + +export const connectWalletSlice = createSlice({ + name: 'connectWallet', + initialState, + reducers: { + showConnectWallet: (state ) => { + state.show = true; + }, + hideConnectWallet: (state) => { + state.show = false; + }, + walletConnecting: (state) => { + state.connecting = true; + state.errMessage = ""; + }, + walletConnected: (state) => { + state.connecting = false; + }, + setErrorMessage: (state, action: PayloadAction) => { + state.errMessage = action.payload; + }, + clearAccounts: (state) => { + state.accounts = []; + }, + resetConnectWallet: state => initialState + }, + extraReducers: (builder) => { + builder.addCase(connect.fulfilled, (state, action: PayloadAction) => { + if (action.payload) { + state.accounts = action.payload; + } + }) + }, +}); + +export const { showConnectWallet, hideConnectWallet, clearAccounts, walletConnecting, walletConnected, setErrorMessage, resetConnectWallet } = connectWalletSlice.actions +export default connectWalletSlice.reducer \ No newline at end of file diff --git a/src/redux/wallet/actions/signer.ts b/src/redux/wallet/actions/signer.ts new file mode 100644 index 00000000..9d765ff7 --- /dev/null +++ b/src/redux/wallet/actions/signer.ts @@ -0,0 +1,23 @@ +import { createSlice } from '@reduxjs/toolkit' + + +export interface Signer { + name: string +} + +const initialState: Signer = { + name: '' +} + +export const signerSlice = createSlice({ + name: 'signer', + initialState, + reducers: { + setSigner: (state, action ) => { + state.name = action.payload; + } + }, +}); + +export const { setSigner } = signerSlice.actions +export default signerSlice.reducer \ No newline at end of file diff --git a/src/redux/wallet/actions/wallet.ts b/src/redux/wallet/actions/wallet.ts new file mode 100644 index 00000000..f2e79738 --- /dev/null +++ b/src/redux/wallet/actions/wallet.ts @@ -0,0 +1,66 @@ +import {createAsyncThunk, createSlice, PayloadAction} from '@reduxjs/toolkit' +import {A_AccountInformation} from "../../../packages/core-sdk/types"; +import {hideLoader, showLoader} from "../../common/actions/loader"; +import {handleException} from "../../common/actions/exception"; +import {AccountClient} from "../../../packages/core-sdk/clients/accountClient"; +import dappflow from "../../../utils/dappflow"; + + +interface Wallet { + information: A_AccountInformation +} + +const information: A_AccountInformation = { + address: "", + amount: 0, + "min-balance": 0, + "amount-without-pending-rewards": 0, + "apps-local-state": [], + "apps-total-schema": { + "num-byte-slice": 0, + "num-uint": 0 + }, + assets: [], + "created-apps": [], + "created-assets": [], + "pending-rewards": 0, + "reward-base": 0, + rewards: 0, + round: 0, + status: "" +} + +const initialState: Wallet = { + information +} + +export const loadWallet = createAsyncThunk( + 'wallet/loadWallet', + async (address: string, thunkAPI) => { + const {dispatch} = thunkAPI; + try { + dispatch(showLoader("Loading wallet details ...")); + const accountInfo = await new AccountClient(dappflow.network).getAccountInformation(address); + dispatch(hideLoader()); + return accountInfo; + } + catch (e: any) { + dispatch(handleException(e)); + dispatch(hideLoader()); + } + } +); + +export const walletSlice = createSlice({ + name: 'wallet', + initialState, + reducers: { + }, + extraReducers: (builder) => { + builder.addCase(loadWallet.fulfilled, (state, action: PayloadAction) => { + state.information = action.payload; + }); + } +}); + +export default walletSlice.reducer \ No newline at end of file From b94c4be79c7a21d4e92e27e07be8d684783818d5 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 8 Nov 2022 22:36:42 +0530 Subject: [PATCH 37/86] connect wallet modal close issue --- .../LeftBar/ConnectWallet/ConnectWallet.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx b/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx index c1475a7d..81c8b036 100644 --- a/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx +++ b/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx @@ -50,10 +50,16 @@ function ConnectWallet(): JSX.Element { } }, [accounts]); + function handleClose() { + dispatch(hideConnectWallet()); + clearState(); + } + return (
{connectWallet.show ? @@ -65,10 +71,7 @@ function ConnectWallet(): JSX.Element { }}/> : ''}
- { - dispatch(hideConnectWallet()); - clearState(); - }}/> +
@@ -144,10 +147,9 @@ function ConnectWallet(): JSX.Element { return (
{ const address = account.address; await dispatch(loadWallet(address)); - dispatch(hideConnectWallet()); localStorage.setItem("signer", selectedSigner.name); localStorage.setItem("address", address); - clearState(); + handleClose(); }}> {account.address}
); From 167ef04a6be495eb45ca08f086f45467ab3d7ba6 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 8 Nov 2022 23:56:25 +0530 Subject: [PATCH 38/86] sign transaction after connecting wallet --- .../LeftBar/ConnectWallet/ConnectWallet.tsx | 25 +++++++++++++-- src/components/LeftBar/LeftBar.scss | 7 +++++ src/components/LeftBar/LeftBar.tsx | 19 +++++++----- .../AppManager/CreateApp/CreateApp.tsx | 31 ++++++++++++++++--- src/packages/core-sdk/constants.ts | 1 + .../transactions/applicationTransaction.ts | 4 +-- .../core-sdk/transactions/baseTransaction.ts | 14 +++++++++ src/packages/signers/algoSigner.ts | 3 +- src/packages/signers/constants/index.ts | 6 ---- src/packages/signers/logicSigner.ts | 2 +- src/packages/signers/myAlgoWalletSigner.ts | 2 +- src/packages/signers/walletSigner.ts | 2 +- src/redux/app/actions/app.ts | 10 ++++++ src/redux/wallet/actions/connectWallet.ts | 13 ++++---- src/utils/dappflow.ts | 6 ++++ 15 files changed, 113 insertions(+), 32 deletions(-) diff --git a/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx b/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx index 81c8b036..0edcd2f2 100644 --- a/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx +++ b/src/components/LeftBar/ConnectWallet/ConnectWallet.tsx @@ -14,6 +14,8 @@ import {ArrowBack, ErrorOutlineOutlined} from "@mui/icons-material"; import CloseIcon from "@mui/icons-material/Close"; import ArrowForwardIcon from '@mui/icons-material/ArrowForward'; import PowerIcon from '@mui/icons-material/Power'; +import {CoreNode} from "../../../packages/core-sdk/classes/core/CoreNode"; +import {NETWORKS} from "../../../packages/core-sdk/constants"; interface ConnectWalletState{ @@ -32,6 +34,24 @@ function ConnectWallet(): JSX.Element { const dispatch = useDispatch(); + const node = useSelector((state: RootState) => state.node); + const {versionsCheck, status, genesis, health} = node; + + let network = ''; + const nodeInstance = new CoreNode(status, versionsCheck, genesis, health); + if (nodeInstance.isTestnet()) { + network = NETWORKS.TESTNET; + } + if (nodeInstance.isBetanet()) { + network = NETWORKS.BETANET; + } + if (nodeInstance.isMainnet()) { + network = NETWORKS.MAINNET; + } + if (nodeInstance.isSandbox()) { + network = NETWORKS.SANDBOX; + } + const connectWallet = useSelector((state: RootState) => state.connectWallet); const {accounts} = connectWallet; @@ -91,7 +111,7 @@ function ConnectWallet(): JSX.Element { return (
{ - dispatch(connect(signer)); + dispatch(connect({signer, network: network})); setState(prevState => ({ ...prevState, view: 'accounts', selectedSigner: signer })); }} > @@ -134,7 +154,8 @@ function ConnectWallet(): JSX.Element { style={{marginTop: 70}} className="black-button" onClick={() => { - dispatch(connect(selectedSigner)); + + dispatch(connect({signer: selectedSigner, network})); }} >Try again
: ''} diff --git a/src/components/LeftBar/LeftBar.scss b/src/components/LeftBar/LeftBar.scss index 2742a03e..85e6059b 100644 --- a/src/components/LeftBar/LeftBar.scss +++ b/src/components/LeftBar/LeftBar.scss @@ -32,6 +32,13 @@ .bottom-menu-item-container { text-align: center; padding: 15px 0; + .small-text { + font-size: 11px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + margin: 0 15px; + } &:hover { cursor: pointer; } diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index 9896dd0f..1d5d9cbb 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -30,6 +30,8 @@ function LeftBar(): JSX.Element { const node = useSelector((state: RootState) => state.node); const location = useLocation(); + const wallet = useSelector((state: RootState) => state.wallet); + const {connection} = liveData; let {success} = connection; let route = location.pathname; @@ -121,13 +123,16 @@ function LeftBar(): JSX.Element {
- + {wallet.information.address ?
{ + dispatch(showConnectWallet()); + }} className="small-text">{wallet.information.address}
: } +
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index a0b75854..af347efa 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -12,7 +12,7 @@ import { } from "@mui/material"; import {FileUploadOutlined} from "@mui/icons-material"; import {theme} from "../../../../theme"; -import {useDispatch} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; import {getFileContent} from "../../../../packages/core-sdk/utils/fileUtils"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import {handleException} from "../../../../redux/common/actions/exception"; @@ -25,6 +25,8 @@ import CloseIcon from "@mui/icons-material/Close"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {isNumber} from "../../../../utils/common"; import {ApplicationTransaction} from "../../../../packages/core-sdk/transactions/applicationTransaction"; +import {RootState} from "../../../../redux/store"; +import {TransactionClient} from "../../../../packages/core-sdk/clients/transactionClient"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -100,6 +102,7 @@ const initialState: CreateAppState = { function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], name: ""}}: CreateAppProps): JSX.Element { const dispatch = useDispatch(); + const wallet = useSelector((state: RootState) => state.wallet); const [ {params}, @@ -186,6 +189,8 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n } try { + dispatch(showLoader('Signing transaction')); + const txnInstance = new ApplicationTransaction(dappflow.network); const unsignedTxn = await txnInstance.prepareCreateTxn({ appApprovalProgram: txnInstance.toUint8Array(approvalProgram), @@ -200,25 +205,41 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n appLocalInts: Number(localInts), appOnComplete: undefined, boxes: [], - extraPages: 0, + extraPages: 2, fee: 0, firstRound: 0, flatFee: false, - from: "CESUKTCKPQZQJ2ZOP5K6M6557S327ZNIWYSIGD7BMLAPFWDJDQWFCHZNMI", + from: wallet.information.address, genesisHash: "", genesisID: "", lastRound: 0, lease: undefined, - reKeyTo: "", + reKeyTo: undefined, suggestedParams: undefined, type: undefined, appAccounts: accounts ? accounts.split(','): [], note: txnInstance.toUint8Array(note) }); - console.log(unsignedTxn); + const signedTxn = await dappflow.signer.signTxn(unsignedTxn); + dispatch(hideLoader()); + + dispatch(showLoader('Broadcasting transaction to network')); + const {txId} = await txnInstance.send(signedTxn); + dispatch(hideLoader()); + + dispatch(showLoader('Waiting for confirmation')); + await txnInstance.waitForConfirmation(txId); + dispatch(hideLoader()); + + dispatch(showLoader('Waiting for confirmation')); + const txn = await new TransactionClient(dappflow.network).get(txId); + dispatch(hideLoader()); + + console.log(txn); } catch (e: any) { + dispatch(hideLoader()); dispatch(handleException(e)); } } diff --git a/src/packages/core-sdk/constants.ts b/src/packages/core-sdk/constants.ts index 298c5245..ff382fd0 100644 --- a/src/packages/core-sdk/constants.ts +++ b/src/packages/core-sdk/constants.ts @@ -23,6 +23,7 @@ export enum PROGRAM_ENCODING { export const TIMESTAMP_DISPLAY_FORMAT = 'ddd, dd mmmm yyyy HH:MM:ss'; export enum NETWORKS { + BETANET = 'betanet', TESTNET = 'testnet', MAINNET = 'mainnet', SANDBOX = 'sandbox' diff --git a/src/packages/core-sdk/transactions/applicationTransaction.ts b/src/packages/core-sdk/transactions/applicationTransaction.ts index 28842a14..256a800a 100644 --- a/src/packages/core-sdk/transactions/applicationTransaction.ts +++ b/src/packages/core-sdk/transactions/applicationTransaction.ts @@ -12,7 +12,7 @@ export class ApplicationTransaction extends BaseTransaction{ async prepareCreateTxn(params: AppCreateTxn): Promise { const suggestedParams = await this.getSuggestedParams(); - const {from, appOnComplete, appApprovalProgram, appClearProgram, appLocalByteSlices, appLocalInts, appGlobalByteSlices, appGlobalInts, appArgs, appForeignApps, appForeignAssets, appAccounts, note} = params; - return sdk.makeApplicationCreateTxn(from, suggestedParams, appOnComplete, appApprovalProgram, appClearProgram, appLocalInts, appLocalByteSlices, appGlobalInts, appGlobalByteSlices, appArgs, appAccounts, appForeignApps, appForeignAssets, note); + const {from, appOnComplete, appApprovalProgram, appClearProgram, appLocalByteSlices, appLocalInts, appGlobalByteSlices, appGlobalInts, appArgs, appForeignApps, appForeignAssets, appAccounts, note, extraPages, reKeyTo, lease, boxes} = params; + return sdk.makeApplicationCreateTxn(from, suggestedParams, appOnComplete, appApprovalProgram, appClearProgram, appLocalInts, appLocalByteSlices, appGlobalInts, appGlobalByteSlices, appArgs, appAccounts, appForeignApps, appForeignAssets, note, lease, reKeyTo, extraPages, boxes); } } \ No newline at end of file diff --git a/src/packages/core-sdk/transactions/baseTransaction.ts b/src/packages/core-sdk/transactions/baseTransaction.ts index db140398..9642a4f8 100644 --- a/src/packages/core-sdk/transactions/baseTransaction.ts +++ b/src/packages/core-sdk/transactions/baseTransaction.ts @@ -1,6 +1,7 @@ import {Algodv2, SuggestedParams} from "algosdk"; import IndexerClient from "algosdk/dist/types/src/client/v2/indexer/indexer"; import {Network} from "../network"; +import {PendingTransactionResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; export class BaseTransaction { @@ -26,4 +27,17 @@ export class BaseTransaction { const enc = new TextEncoder(); return enc.encode(text); } + + async waitForConfirmation(txId: string): Promise { + const status = await this.client.status().do(); + let lastRound = status["last-round"]; + while (true) { + const pendingInfo = await this.client.pendingTransactionInformation(txId).do(); + if (pendingInfo["confirmed-round"] !== null && pendingInfo["confirmed-round"] > 0) { + return pendingInfo as PendingTransactionResponse; + } + lastRound++; + await this.client.statusAfterBlock(lastRound).do(); + } + }; } \ No newline at end of file diff --git a/src/packages/signers/algoSigner.ts b/src/packages/signers/algoSigner.ts index d57db6cc..ab01c3f9 100644 --- a/src/packages/signers/algoSigner.ts +++ b/src/packages/signers/algoSigner.ts @@ -1,6 +1,7 @@ import {Signer, SignerAccount} from "./types"; import {Transaction} from "algosdk"; -import {ALGO_SIGNER_NET, NETWORKS} from "./constants"; +import {ALGO_SIGNER_NET} from "./constants"; +import {NETWORKS} from "../core-sdk/constants"; export class BrowserAlgoSigner implements Signer{ private supportedNetworks: string[]; diff --git a/src/packages/signers/constants/index.ts b/src/packages/signers/constants/index.ts index beb6a871..e0b554ed 100644 --- a/src/packages/signers/constants/index.ts +++ b/src/packages/signers/constants/index.ts @@ -1,9 +1,3 @@ -export enum NETWORKS { - BETANET = "betanet", - TESTNET = 'testnet', - MAINNET = 'mainnet' -} - export enum SIGNERS { WALLET = 'wallet', ALGO_SIGNER = 'algo_signer', diff --git a/src/packages/signers/logicSigner.ts b/src/packages/signers/logicSigner.ts index 8cf380a2..2a42c322 100644 --- a/src/packages/signers/logicSigner.ts +++ b/src/packages/signers/logicSigner.ts @@ -1,7 +1,7 @@ import {Signer} from "./types"; import * as sdk from "algosdk"; -import {NETWORKS} from "./constants"; import {LogicSigAccount} from "algosdk"; +import {NETWORKS} from "../core-sdk/constants"; export class LogicSigner implements Signer{ diff --git a/src/packages/signers/myAlgoWalletSigner.ts b/src/packages/signers/myAlgoWalletSigner.ts index 31a3f144..fd7dd02b 100644 --- a/src/packages/signers/myAlgoWalletSigner.ts +++ b/src/packages/signers/myAlgoWalletSigner.ts @@ -1,7 +1,7 @@ import {Signer, SignerAccount} from "./types"; import {Transaction} from "algosdk"; import MyAlgoConnect from '@randlabs/myalgo-connect'; -import {NETWORKS} from "./constants"; +import {NETWORKS} from "../core-sdk/constants"; export class MyAlgoWalletSigner implements Signer{ diff --git a/src/packages/signers/walletSigner.ts b/src/packages/signers/walletSigner.ts index 8795ef10..89a26e3e 100644 --- a/src/packages/signers/walletSigner.ts +++ b/src/packages/signers/walletSigner.ts @@ -1,6 +1,6 @@ import {Signer} from "./types"; import {Account, Transaction} from "algosdk"; -import {NETWORKS} from "./constants"; +import {NETWORKS} from "../core-sdk/constants"; export class WalletSigner implements Signer{ private wallet: Account; diff --git a/src/redux/app/actions/app.ts b/src/redux/app/actions/app.ts index 484ea641..a8a2e65c 100644 --- a/src/redux/app/actions/app.ts +++ b/src/redux/app/actions/app.ts @@ -1,5 +1,8 @@ import {createAsyncThunk, createSlice} from '@reduxjs/toolkit'; import {loadNodeDetails} from "../../network/actions/node"; +import {setSigner} from "../../wallet/actions/signer"; +import dappflow from "../../../utils/dappflow"; +import {loadWallet} from "../../wallet/actions/wallet"; export const initApp = createAsyncThunk( @@ -7,6 +10,13 @@ export const initApp = createAsyncThunk( async (_, thunkAPI) => { const {dispatch} = thunkAPI; dispatch(loadNodeDetails()); + const selectedSigner = localStorage.getItem("signer"); + const selectedAddress = localStorage.getItem("address"); + if(selectedSigner && selectedAddress) { + dispatch(setSigner(selectedSigner)); + dappflow.setSigner(selectedSigner); + dispatch(loadWallet(selectedAddress)); + } } ); diff --git a/src/redux/wallet/actions/connectWallet.ts b/src/redux/wallet/actions/connectWallet.ts index 1aa32284..77b10065 100644 --- a/src/redux/wallet/actions/connectWallet.ts +++ b/src/redux/wallet/actions/connectWallet.ts @@ -3,6 +3,7 @@ import {SignerAccount} from "../../../packages/signers/types"; import {SupportedSigner} from "../../../packages/signers"; import {setSigner} from "./signer"; import {loadWallet} from "./wallet"; +import dappflow from "../../../utils/dappflow"; export interface ConnectWallet { @@ -21,18 +22,18 @@ const initialState: ConnectWallet = { export const connect = createAsyncThunk( 'connectWallet/connect', - async (signer: SupportedSigner, thunkAPI) => { - const {dispatch, getState} = thunkAPI; + async (payload: { signer: SupportedSigner, network: string }, thunkAPI) => { + const {dispatch} = thunkAPI; try { - console.log(signer); - const appState: any = getState(); - const {network} = appState; + const {signer, network} = payload; + dispatch(walletConnecting()); dispatch(clearAccounts()); dispatch(setSigner(signer.name)); + dappflow.setSigner(signer.name); // @ts-ignore - const accounts = await signer.instance.connect(network.name, (err, payload)=> { + const accounts = await signer.instance.connect(network, (err, payload)=> { dispatch(walletConnected()); dispatch(setErrorMessage(payload.params[0].message)); }); diff --git a/src/utils/dappflow.ts b/src/utils/dappflow.ts index 5dca8b85..5d0dd10b 100644 --- a/src/utils/dappflow.ts +++ b/src/utils/dappflow.ts @@ -3,6 +3,8 @@ import {Network} from "../packages/core-sdk/network"; import { getNodeConfig } from "./nodeConfig"; +import {Signer} from "../packages/signers/types"; +import {getSigner} from "../packages/signers"; function getNetwork() { @@ -12,11 +14,15 @@ function getNetwork() { class Dappflow { network: Network + signer: Signer constructor() { this.network = getNetwork(); } + setSigner(signer: string): void { + this.signer = getSigner(signer); + } } export default new Dappflow(); \ No newline at end of file From 0d6b3a9783a945e14bc6ea04defc5bcdf86691c5 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Mon, 14 Nov 2022 21:05:57 +0530 Subject: [PATCH 39/86] switch wallet and disconnect wallet --- src/components/LeftBar/LeftBar.tsx | 57 ++++++++++++++++++++++++------ src/redux/wallet/actions/wallet.ts | 2 ++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index 1d5d9cbb..faa6d891 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -1,7 +1,7 @@ import './LeftBar.scss'; import { Box, - Button, Tab, Tabs + Button, Menu, MenuItem, Tab, Tabs } from "@mui/material"; import {useDispatch, useSelector} from "react-redux"; import React from "react"; @@ -19,8 +19,10 @@ import ShowerIcon from '@mui/icons-material/Shower'; import InsertChartIcon from '@mui/icons-material/InsertChart'; import {CoreNode} from "../../packages/core-sdk/classes/core/CoreNode"; import {supportSettings} from "../../utils/nodeConfig"; -import {showConnectWallet} from "../../redux/wallet/actions/connectWallet"; +import {resetConnectWallet, showConnectWallet} from "../../redux/wallet/actions/connectWallet"; import ConnectWallet from "./ConnectWallet/ConnectWallet"; +import dappflow from "../../utils/dappflow"; +import {resetWallet} from "../../redux/wallet/actions/wallet"; function LeftBar(): JSX.Element { @@ -38,6 +40,14 @@ function LeftBar(): JSX.Element { route = route.substring(1); route = route.split('/')[0]; + const [anchorEl, setAnchorEl] = React.useState(null); + const open = Boolean(anchorEl); + const handleClick = (event: any) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; return (
@@ -123,14 +133,41 @@ function LeftBar(): JSX.Element {
- {wallet.information.address ?
{ - dispatch(showConnectWallet()); - }} className="small-text">{wallet.information.address}
: } diff --git a/src/redux/wallet/actions/wallet.ts b/src/redux/wallet/actions/wallet.ts index f2e79738..92e644f9 100644 --- a/src/redux/wallet/actions/wallet.ts +++ b/src/redux/wallet/actions/wallet.ts @@ -55,6 +55,7 @@ export const walletSlice = createSlice({ name: 'wallet', initialState, reducers: { + resetWallet: state => initialState }, extraReducers: (builder) => { builder.addCase(loadWallet.fulfilled, (state, action: PayloadAction) => { @@ -63,4 +64,5 @@ export const walletSlice = createSlice({ } }); +export const { resetWallet } = walletSlice.actions export default walletSlice.reducer \ No newline at end of file From 085f8c9113c2270417e69905ee0e02c89b0970db Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Mon, 14 Nov 2022 21:19:43 +0530 Subject: [PATCH 40/86] force wallet disconnect up on node config update --- src/components/LeftBar/LeftBar.tsx | 10 +++------- src/components/LeftBar/Settings/Settings.tsx | 2 ++ src/redux/wallet/actions/wallet.ts | 11 +++++++++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index faa6d891..bf5d7cd0 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -19,10 +19,9 @@ import ShowerIcon from '@mui/icons-material/Shower'; import InsertChartIcon from '@mui/icons-material/InsertChart'; import {CoreNode} from "../../packages/core-sdk/classes/core/CoreNode"; import {supportSettings} from "../../utils/nodeConfig"; -import {resetConnectWallet, showConnectWallet} from "../../redux/wallet/actions/connectWallet"; +import {showConnectWallet} from "../../redux/wallet/actions/connectWallet"; import ConnectWallet from "./ConnectWallet/ConnectWallet"; -import dappflow from "../../utils/dappflow"; -import {resetWallet} from "../../redux/wallet/actions/wallet"; +import {logOut} from "../../redux/wallet/actions/wallet"; function LeftBar(): JSX.Element { @@ -152,10 +151,7 @@ function LeftBar(): JSX.Element { } }>Switch wallet { - dappflow.signer.logout(); - dispatch(resetWallet()); - localStorage.removeItem("signer"); - localStorage.removeItem("address"); + dispatch(logOut()); handleClose(); e.preventDefault(); e.stopPropagation(); diff --git a/src/components/LeftBar/Settings/Settings.tsx b/src/components/LeftBar/Settings/Settings.tsx index aece3967..000fca45 100644 --- a/src/components/LeftBar/Settings/Settings.tsx +++ b/src/components/LeftBar/Settings/Settings.tsx @@ -21,6 +21,7 @@ import {hideLoader, showLoader} from "../../../redux/common/actions/loader"; import {isBrave} from "../../../packages/core-sdk/utils"; import {NodeConnectionParams} from "../../../packages/core-sdk/types"; import CloseIcon from '@mui/icons-material/Close'; +import {logOut} from "../../../redux/wallet/actions/wallet"; const nodeConfig = getNodeConfig(); @@ -160,6 +161,7 @@ function Settings(): JSX.Element { localStorage.setItem('indexerToken', indexerToken || ''); dispatch(hideSettings()); dispatch(hideLoader()); + dispatch(logOut()); window.location.reload(); } diff --git a/src/redux/wallet/actions/wallet.ts b/src/redux/wallet/actions/wallet.ts index 92e644f9..921c253e 100644 --- a/src/redux/wallet/actions/wallet.ts +++ b/src/redux/wallet/actions/wallet.ts @@ -51,6 +51,17 @@ export const loadWallet = createAsyncThunk( } ); +export const logOut = createAsyncThunk( + 'wallet/logOut', + async (_, thunkAPI) => { + const {dispatch} = thunkAPI; + dappflow.signer.logout(); + dispatch(resetWallet()); + localStorage.removeItem("signer"); + localStorage.removeItem("address"); + } +); + export const walletSlice = createSlice({ name: 'wallet', initialState, From 2e3d9e613ae5b3d6f45123c44acfaebed980d96d Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Mon, 14 Nov 2022 21:55:59 +0530 Subject: [PATCH 41/86] wallet action menu --- src/components/LeftBar/LeftBar.scss | 3 +- src/components/LeftBar/LeftBar.tsx | 65 +++++++++++++++++++++-------- 2 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/components/LeftBar/LeftBar.scss b/src/components/LeftBar/LeftBar.scss index 85e6059b..88294809 100644 --- a/src/components/LeftBar/LeftBar.scss +++ b/src/components/LeftBar/LeftBar.scss @@ -33,11 +33,12 @@ text-align: center; padding: 15px 0; .small-text { - font-size: 11px; + font-size: 12px; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; margin: 0 15px; + font-weight: bold; } &:hover { cursor: pointer; diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index bf5d7cd0..c9942dd8 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -1,7 +1,7 @@ import './LeftBar.scss'; import { Box, - Button, Menu, MenuItem, Tab, Tabs + Button, ListItemIcon, ListItemText, Menu, MenuItem, Tab, Tabs } from "@mui/material"; import {useDispatch, useSelector} from "react-redux"; import React from "react"; @@ -22,6 +22,9 @@ import {supportSettings} from "../../utils/nodeConfig"; import {showConnectWallet} from "../../redux/wallet/actions/connectWallet"; import ConnectWallet from "./ConnectWallet/ConnectWallet"; import {logOut} from "../../redux/wallet/actions/wallet"; +import LogoutIcon from '@mui/icons-material/Logout'; +import SwapCallsIcon from '@mui/icons-material/SwapCalls'; +import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; function LeftBar(): JSX.Element { @@ -39,12 +42,14 @@ function LeftBar(): JSX.Element { route = route.substring(1); route = route.split('/')[0]; - const [anchorEl, setAnchorEl] = React.useState(null); - const open = Boolean(anchorEl); - const handleClick = (event: any) => { + const [menuAnchorEl, setAnchorEl] = React.useState(null); + const open = Boolean(menuAnchorEl); + + const showWalletMenu = (event: any) => { setAnchorEl(event.currentTarget); }; - const handleClose = () => { + + const closeWalletMenu = () => { setAnchorEl(null); }; @@ -132,30 +137,56 @@ function LeftBar(): JSX.Element {
- {wallet.information.address ?
+ {wallet.information.address ?
- +
+ {wallet.information.address} - +
- { + disableAutoFocusItem={true} + anchorOrigin={{ + vertical: 'top', + horizontal: 'left', + }} + transformOrigin={{ + vertical: 'top', + horizontal: 'left', + }} + MenuListProps={{ + + }} + onClose={closeWalletMenu}> + { dispatch(showConnectWallet()); - handleClose(); + closeWalletMenu(); e.preventDefault(); e.stopPropagation(); } - }>Switch wallet - { + }> + + + + Switch wallet + + { dispatch(logOut()); - handleClose(); + closeWalletMenu(); e.preventDefault(); e.stopPropagation(); - }}>Disconnect + }}> + + + + Disconnect +
: From 5d0ea94d595b8aabab34ed92fe4668104c7a2849 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 16 Nov 2022 11:48:53 +0530 Subject: [PATCH 43/86] update ABIConfig upon app creation --- .../AppManager/CreateApp/CreateApp.tsx | 27 +++++++++++-------- .../transactions/applicationTransaction.ts | 4 +++ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index af347efa..97273aea 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -27,6 +27,8 @@ import {isNumber} from "../../../../utils/common"; import {ApplicationTransaction} from "../../../../packages/core-sdk/transactions/applicationTransaction"; import {RootState} from "../../../../redux/store"; import {TransactionClient} from "../../../../packages/core-sdk/clients/transactionClient"; +import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; +import {CoreTransaction} from "../../../../packages/core-sdk/classes/core/CoreTransaction"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -191,11 +193,11 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n try { dispatch(showLoader('Signing transaction')); - const txnInstance = new ApplicationTransaction(dappflow.network); - const unsignedTxn = await txnInstance.prepareCreateTxn({ - appApprovalProgram: txnInstance.toUint8Array(approvalProgram), + const appCallInstance = new ApplicationTransaction(dappflow.network); + const unsignedTxn = await appCallInstance.prepareCreateTxn({ + appApprovalProgram: appCallInstance.getProgramBytes(approvalProgram), appArgs: [], - appClearProgram: txnInstance.toUint8Array(clearProgram), + appClearProgram: appCallInstance.getProgramBytes(clearProgram), appForeignApps: foreignApps ? foreignApps.split(',').map(app => Number(app)): [], appForeignAssets: foreignAssets ? foreignAssets.split(',').map(asset => Number(asset)): [], appGlobalByteSlices: Number(globalBytes), @@ -218,25 +220,28 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n suggestedParams: undefined, type: undefined, appAccounts: accounts ? accounts.split(','): [], - note: txnInstance.toUint8Array(note) + note: appCallInstance.toUint8Array(note) }); const signedTxn = await dappflow.signer.signTxn(unsignedTxn); dispatch(hideLoader()); dispatch(showLoader('Broadcasting transaction to network')); - const {txId} = await txnInstance.send(signedTxn); - dispatch(hideLoader()); - - dispatch(showLoader('Waiting for confirmation')); - await txnInstance.waitForConfirmation(txId); + const {txId} = await appCallInstance.send(signedTxn); dispatch(hideLoader()); dispatch(showLoader('Waiting for confirmation')); + await appCallInstance.waitForConfirmation(txId); const txn = await new TransactionClient(dappflow.network).get(txId); dispatch(hideLoader()); - console.log(txn); + const txnInstance = new CoreTransaction(txn); + new ABIConfig().setAppId(txnInstance.getAppId().toString()); + handleClose(); + dispatch(showSnack({ + severity: 'success', + message: 'Application created successfully. You can execute the ABI calls.' + })); } catch (e: any) { dispatch(hideLoader()); diff --git a/src/packages/core-sdk/transactions/applicationTransaction.ts b/src/packages/core-sdk/transactions/applicationTransaction.ts index 256a800a..f247baa7 100644 --- a/src/packages/core-sdk/transactions/applicationTransaction.ts +++ b/src/packages/core-sdk/transactions/applicationTransaction.ts @@ -10,6 +10,10 @@ export class ApplicationTransaction extends BaseTransaction{ super(network); } + getProgramBytes(program: string): Uint8Array { + return new Uint8Array(Buffer.from(program, "base64")); + } + async prepareCreateTxn(params: AppCreateTxn): Promise { const suggestedParams = await this.getSuggestedParams(); const {from, appOnComplete, appApprovalProgram, appClearProgram, appLocalByteSlices, appLocalInts, appGlobalByteSlices, appGlobalInts, appArgs, appForeignApps, appForeignAssets, appAccounts, note, extraPages, reKeyTo, lease, boxes} = params; From 817311facff3fadb9ca7fa658a2e20eeccbcdcc1 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 16 Nov 2022 12:36:16 +0530 Subject: [PATCH 44/86] ability to sign tarnsactions from sandbox using algosigner --- .../LeftBar/ConnectWallet/ConnectWallet.scss | 13 +++++-------- src/components/Modules/Dispenser/Dispenser.tsx | 2 +- src/packages/signers/algoSigner.ts | 16 ++++++++++++---- src/packages/signers/constants/index.ts | 3 ++- 4 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/components/LeftBar/ConnectWallet/ConnectWallet.scss b/src/components/LeftBar/ConnectWallet/ConnectWallet.scss index 0d50fec9..1423c61c 100644 --- a/src/components/LeftBar/ConnectWallet/ConnectWallet.scss +++ b/src/components/LeftBar/ConnectWallet/ConnectWallet.scss @@ -92,18 +92,15 @@ } } .account { - font-size: 14px; - font-weight: bold; + font-size: 12px; overflow-wrap: anywhere; - margin: 15px 40px; - background: #D7F7E2; - color: $color-dark; - padding: 15px; + margin: 10px 40px; + padding: 10px; border-radius: 10px; - line-height: 1.4; + border: 1px solid $color-grey-light; &:hover { - background: linear-gradient(249.61deg, #60DD8B -8.07%, #0BB68C 99.24%); cursor: pointer; + background: $color-dark; color: $color-light; } } diff --git a/src/components/Modules/Dispenser/Dispenser.tsx b/src/components/Modules/Dispenser/Dispenser.tsx index 1295d146..af693d06 100644 --- a/src/components/Modules/Dispenser/Dispenser.tsx +++ b/src/components/Modules/Dispenser/Dispenser.tsx @@ -71,7 +71,7 @@ function Dispenser(): JSX.Element { } function setSuccess(txId: string) { - setState(prevState => ({...prevState, success: true, error: false, txId, errMsg: "", address: ""})); + setState(prevState => ({...prevState, success: true, error: false, txId, errMsg: "", address: "", amount: ""})); } function setError(message: string) { diff --git a/src/packages/signers/algoSigner.ts b/src/packages/signers/algoSigner.ts index ab01c3f9..10df81fd 100644 --- a/src/packages/signers/algoSigner.ts +++ b/src/packages/signers/algoSigner.ts @@ -1,5 +1,5 @@ import {Signer, SignerAccount} from "./types"; -import {Transaction} from "algosdk"; +import {generateAccount, secretKeyToMnemonic, Transaction} from "algosdk"; import {ALGO_SIGNER_NET} from "./constants"; import {NETWORKS} from "../core-sdk/constants"; @@ -7,7 +7,7 @@ export class BrowserAlgoSigner implements Signer{ private supportedNetworks: string[]; constructor() { - this.supportedNetworks = [NETWORKS.TESTNET, NETWORKS.MAINNET]; + this.supportedNetworks = [NETWORKS.TESTNET, NETWORKS.MAINNET, NETWORKS.BETANET, NETWORKS.SANDBOX]; } async signTxn(unsignedTxn: Transaction): Promise { @@ -59,7 +59,7 @@ export class BrowserAlgoSigner implements Signer{ return this.supportedNetworks.indexOf(name) !== -1; } - getAlgoSignerNet(name: string): string { + getAlgoSignerLedger(name: string): string | any { if (name === NETWORKS.MAINNET) { return ALGO_SIGNER_NET.MAINNET } @@ -69,9 +69,17 @@ export class BrowserAlgoSigner implements Signer{ if (name === NETWORKS.TESTNET) { return ALGO_SIGNER_NET.TESTNET } + if (name === NETWORKS.SANDBOX) { + return ALGO_SIGNER_NET.SANDBOX + } } async connect(name: string): Promise { + const test = generateAccount(); + console.log(secretKeyToMnemonic(test.sk)); + const algoSignerLedger = this.getAlgoSignerLedger(name); + + console.log(algoSignerLedger); if (this.isInstalled()) { if (this.isNetworkSupported(name)) { const accounts: SignerAccount[] = []; @@ -79,7 +87,7 @@ export class BrowserAlgoSigner implements Signer{ await AlgoSigner.connect(); // @ts-ignore const wallets = await AlgoSigner.accounts({ - ledger: this.getAlgoSignerNet(name) + ledger: algoSignerLedger }); if (wallets) { diff --git a/src/packages/signers/constants/index.ts b/src/packages/signers/constants/index.ts index e0b554ed..e78c4a60 100644 --- a/src/packages/signers/constants/index.ts +++ b/src/packages/signers/constants/index.ts @@ -8,5 +8,6 @@ export enum SIGNERS { export enum ALGO_SIGNER_NET { BETANET = "BetaNet", TESTNET = 'TestNet', - MAINNET = 'MainNet' + MAINNET = 'MainNet', + SANDBOX = 'sandnet-v1' } From 60e618193d78d72b3833f012a677b77df1dcf9d1 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 16 Nov 2022 21:11:02 +0530 Subject: [PATCH 45/86] invoke ABI method calls --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 34 +++++++++++++++++-- .../AppManager/CreateApp/CreateApp.tsx | 8 ++--- src/packages/signers/algoSigner.ts | 5 +-- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index bfc47ece..692e52db 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -14,13 +14,18 @@ import { } from "@mui/material"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {theme} from "../../../../theme"; -import {useDispatch} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {handleException} from "../../../../redux/common/actions/exception"; import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; import {A_ABI_METHOD_EXECUTOR_ARG} from "../../../../packages/abi/types"; import CloseIcon from "@mui/icons-material/Close"; +import {RootState} from "../../../../redux/store"; +import dappflow from "../../../../utils/dappflow"; +import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; +import {TransactionClient} from "../../../../packages/core-sdk/clients/transactionClient"; +import {BaseTransaction} from "../../../../packages/core-sdk/transactions/baseTransaction"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -64,6 +69,7 @@ const initialState: ABIMethodExecutorState = { function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.method, handleClose}: ABIMethodExecutorProps): JSX.Element { + const wallet = useSelector((state: RootState) => state.wallet); const dispatch = useDispatch(); const [ {appId, executorArgs}, @@ -111,9 +117,31 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth } try { + dispatch(showLoader('Signing transaction')); const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); - const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), 'CESUKTCKPQZQJ2ZOP5K6M6557S327ZNIWYSIGD7BMLAPFWDJDQWFCHZNMI', executorArgs); - console.log(unsignedTxns); + const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), wallet.information.address, executorArgs); + + const signedTxns = await dappflow.signer.signGroupTxns(unsignedTxns.map((unsignedTxn) => { + return unsignedTxn.txn; + })); + dispatch(hideLoader()); + + const txnInstance = new BaseTransaction(dappflow.network); + dispatch(showLoader('Broadcasting transaction to network')); + const {txId} = await txnInstance.send(signedTxns); + dispatch(hideLoader()); + + dispatch(showLoader('Waiting for confirmation')); + await txnInstance.waitForConfirmation(txId); + const txn = await new TransactionClient(dappflow.network).get(txId); + console.log(txn); + dispatch(hideLoader()); + + handleClose(); + dispatch(showSnack({ + severity: 'success', + message: 'Method executed successfully: ' + txId + })); } catch (e: any) { dispatch(handleException(e)); diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 97273aea..555c1b20 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -398,7 +398,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n multiline rows={3} value={params.foreignAssets} - placeholder="Note" + placeholder="Comma separated list of foreign assets" onChange={(ev) => { setState(prevState => ({...prevState, params: { ...params, @@ -415,7 +415,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n multiline rows={3} value={params.foreignApps} - placeholder="Note" + placeholder="Comma separated list of foreign apps" onChange={(ev) => { setState(prevState => ({...prevState, params: { ...params, @@ -432,7 +432,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n multiline rows={3} value={params.accounts} - placeholder="Note" + placeholder="Comma separated list of accounts" onChange={(ev) => { setState(prevState => ({...prevState, params: { ...params, @@ -449,7 +449,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n multiline rows={3} value={params.note} - placeholder="Note" + placeholder="Enter your note" onChange={(ev) => { setState(prevState => ({...prevState, params: { ...params, diff --git a/src/packages/signers/algoSigner.ts b/src/packages/signers/algoSigner.ts index 10df81fd..6cb799e0 100644 --- a/src/packages/signers/algoSigner.ts +++ b/src/packages/signers/algoSigner.ts @@ -1,5 +1,5 @@ import {Signer, SignerAccount} from "./types"; -import {generateAccount, secretKeyToMnemonic, Transaction} from "algosdk"; +import {Transaction} from "algosdk"; import {ALGO_SIGNER_NET} from "./constants"; import {NETWORKS} from "../core-sdk/constants"; @@ -75,11 +75,8 @@ export class BrowserAlgoSigner implements Signer{ } async connect(name: string): Promise { - const test = generateAccount(); - console.log(secretKeyToMnemonic(test.sk)); const algoSignerLedger = this.getAlgoSignerLedger(name); - console.log(algoSignerLedger); if (this.isInstalled()) { if (this.isNetworkSupported(name)) { const accounts: SignerAccount[] = []; From f1b22277c2fee3a6d6b4c20a0517a1707d560769 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Thu, 17 Nov 2022 00:01:25 +0530 Subject: [PATCH 46/86] App creation UI enhancements and bug fixes --- src/components/LeftBar/Settings/Settings.tsx | 2 + .../Modules/ABI/ABIEditor/ABIEditor.scss | 3 +- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 88 ++++++++++--------- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 12 ++- .../Modules/ABI/ABIStudio/ABIStudio.tsx | 2 + .../AppManager/CreateApp/CreateApp.tsx | 4 +- 6 files changed, 65 insertions(+), 46 deletions(-) diff --git a/src/components/LeftBar/Settings/Settings.tsx b/src/components/LeftBar/Settings/Settings.tsx index 000fca45..eefe489d 100644 --- a/src/components/LeftBar/Settings/Settings.tsx +++ b/src/components/LeftBar/Settings/Settings.tsx @@ -22,6 +22,7 @@ import {isBrave} from "../../../packages/core-sdk/utils"; import {NodeConnectionParams} from "../../../packages/core-sdk/types"; import CloseIcon from '@mui/icons-material/Close'; import {logOut} from "../../../redux/wallet/actions/wallet"; +import ABIConfig from "../../../packages/abi/classes/ABIConfig"; const nodeConfig = getNodeConfig(); @@ -162,6 +163,7 @@ function Settings(): JSX.Element { dispatch(hideSettings()); dispatch(hideLoader()); dispatch(logOut()); + new ABIConfig().setAppId(""); window.location.reload(); } diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.scss b/src/components/Modules/ABI/ABIEditor/ABIEditor.scss index 18f4bb56..277caf9b 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.scss +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.scss @@ -15,11 +15,10 @@ .abi-name { font-size: 20px; font-family: PoppinsBold !important; - margin-bottom: 15px; + margin-bottom: 10px; color: #000 !important; } .abi-desc { - margin-top: 15px; font-size: 14px; color: $color-grey-dark; } diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 1c6be7fc..244288fa 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -2,12 +2,11 @@ import './ABIEditor.scss'; import React, {useState} from "react"; import {shadedClr, shadedClr2} from "../../../../utils/common"; import JsonViewer from "../../../Common/JsonViewer/JsonViewer"; -import {Box, Button} from "@mui/material"; +import {Box, Button, Grid} from "@mui/material"; import ABIMethods from "../ABIMethods/ABIMethods"; import ABINetworks from "../ABINetworks/ABINetworks"; import {ABIContract, ABIContractParams} from "algosdk"; import ABIConfig from "../ABIConfig/ABIConfig"; -import SettingsIcon from '@mui/icons-material/Settings'; import CreateApp from "../../AppManager/CreateApp/CreateApp"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {useDispatch, useSelector} from "react-redux"; @@ -47,48 +46,55 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support
-
-
- ABI: {abiInstance.name} -
-
- Description: {abiInstance.description ? abiInstance.description : '--Empty--'} -
-
-
- - {supportExecutor ?
- - {setState(prevState => ({...prevState, showConfig: false}));}}> -
: ''} + + +
+
+ ABI: {abiInstance.name} +
+
+ Description: {abiInstance.description ? abiInstance.description : '--Empty--'} +
+
+
+ +
+ + {supportExecutor ?
+ + {setState(prevState => ({...prevState, showConfig: false}));}}> +
: ''} - {supportCreateApp ?
- + {setState(prevState => ({...prevState, showCreateApp: false}));}}> +
: ''} + +
+
+
- setState(prevState => ({...prevState, showCreateApp: true})); - }} - >Create App - {setState(prevState => ({...prevState, showCreateApp: false}));}}> -
: ''} -
{!hideNetworks ? : ''} diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index d6a624a1..3855429e 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -14,8 +14,9 @@ import ABIMethodExecutor from "../ABIMethodExecutor/ABIMethodExecutor"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {Alert} from "@mui/lab"; import {showSnack} from "../../../../redux/common/actions/snackbar"; -import {useDispatch} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; +import {RootState} from "../../../../redux/store"; type ABIMethodProps = { method: ABIMethodParams, @@ -33,6 +34,7 @@ const initialState: ABIMethodState = { function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Element { const dispatch = useDispatch(); + const wallet = useSelector((state: RootState) => state.wallet); const abiMethodInstance = new ABIMethodSDK(method); const args = abiMethodInstance.args; @@ -59,6 +61,14 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen ev.preventDefault(); ev.stopPropagation(); + if (!wallet.information.address) { + dispatch(showSnack({ + severity: 'error', + message: 'Please connect your wallet' + })); + return; + } + if (!new ABIMethodExecutorCls(method).canExecute()) { dispatch(showSnack({ severity: 'error', diff --git a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx index bf9c0512..eed13cab 100644 --- a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx +++ b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx @@ -3,6 +3,7 @@ import React, {useEffect, useState} from "react"; import ABIEditor from "../ABIEditor/ABIEditor"; import ABIActions from "../ABIActions/ABIActions"; import {ABIContractParams} from "algosdk"; +import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; interface ABIStudioState{ imported: boolean, @@ -44,6 +45,7 @@ function ABIStudio(): JSX.Element {
{ setState(prevState => ({...prevState, abi, imported: true})); + new ABIConfig().setAppId(""); localStorage.setItem('abi', JSON.stringify(abi)); }}> {imported ? : ''} diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 555c1b20..c1118e51 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -398,7 +398,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n multiline rows={3} value={params.foreignAssets} - placeholder="Comma separated list of foreign assets" + placeholder="Comma separated list of assets" onChange={(ev) => { setState(prevState => ({...prevState, params: { ...params, @@ -415,7 +415,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n multiline rows={3} value={params.foreignApps} - placeholder="Comma separated list of foreign apps" + placeholder="Comma separated list of apps" onChange={(ev) => { setState(prevState => ({...prevState, params: { ...params, From 1d0d9fd2027101682d8c0364c18c17a616ee32d0 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Fri, 18 Nov 2022 13:54:47 +0530 Subject: [PATCH 47/86] algopoap contract to ABI --- src/components/Modules/ABI/ImportABI/ImportABI.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.tsx b/src/components/Modules/ABI/ImportABI/ImportABI.tsx index 32cd3767..745dc3c9 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.tsx +++ b/src/components/Modules/ABI/ImportABI/ImportABI.tsx @@ -164,6 +164,13 @@ function ImportABI(props): JSX.Element { }} label="DAO ABI" size="small" color={"warning"} variant={"outlined"} sx={{marginLeft: '10px'}} > + + { + setState(prevState => ({...prevState, url: "https://raw.githubusercontent.com/AlgoPoaP/algopoap-smartcontracts/main/algopoap-contract.json"})); + }} label="AlgoPoaP ABI" size="small" color={"warning"} variant={"outlined"} + sx={{marginLeft: '10px'}} + > +
From bebea80f732ca905bbed77ec126e5908e4927a2f Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Fri, 18 Nov 2022 17:18:07 +0530 Subject: [PATCH 48/86] support group transactions: payment --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 4 +- src/packages/abi/classes/ABIMethodExecutor.ts | 58 +++++++++++++++---- src/packages/abi/types.ts | 2 +- 3 files changed, 49 insertions(+), 15 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 692e52db..71910e5c 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -133,8 +133,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth dispatch(showLoader('Waiting for confirmation')); await txnInstance.waitForConfirmation(txId); - const txn = await new TransactionClient(dappflow.network).get(txId); - console.log(txn); + await new TransactionClient(dappflow.network).get(txId); dispatch(hideLoader()); handleClose(); @@ -144,6 +143,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth })); } catch (e: any) { + dispatch(hideLoader()); dispatch(handleException(e)); } } diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index b9161d58..4e945015 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -4,7 +4,10 @@ import { ABIMethodParams, ABITransactionType, abiTypeIsTransaction, - AtomicTransactionComposer, TransactionWithSigner + AtomicTransactionComposer, makeBasicAccountTransactionSigner, + Transaction, + TransactionType, + TransactionWithSigner } from "algosdk"; import {A_ABI_METHOD_EXECUTOR_ARG, ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; import dappflow from "../../../utils/dappflow"; @@ -22,10 +25,6 @@ export default class ABIMethodExecutor { } canExecute(): boolean { - if (this.isGroup()) { - return false; - } - let supported = true; const txnTypes = this.getTxnTypes(); @@ -70,31 +69,66 @@ export default class ABIMethodExecutor { return BigInt(val); case "bool": return Boolean(val); + case "byte[]": + return new Uint8Array(Buffer.from(val, "base64")); default: return val; } } + getSequenceOfTxnTypes(): string[] { + const txnTypes: string[] = []; + + const args = this.getArgs(); + args.forEach((arg) => { + if (abiTypeIsTransaction(arg.type.toString())) { + txnTypes.push(arg.type.toString()); + } + else { + if (txnTypes.indexOf('current') === -1) { + txnTypes.push('current'); + } + } + }); + + return txnTypes; + } + async getUnsignedTxns(appId: number, from: string, args: A_ABI_METHOD_EXECUTOR_ARG[] = []): Promise { + console.log(this.getSequenceOfTxnTypes()); const atc = new AtomicTransactionComposer(); const sp = await new BaseTransaction(dappflow.network).getSuggestedParams(); + const signer = undefined; const appCallParams = { appID: appId, sender: from, - suggestedParams:sp, - signer: undefined + suggestedParams: sp, + signer } - const methodArgs = args.map((arg) => - this.parseArgumentValue(arg) - ).filter((value) => value !== undefined && value !== "" && value !== null); + console.log(sp); + const methodArgs = args.map((arg) => { + const val = this.parseArgumentValue(arg); + if (abiTypeIsTransaction(arg.type.toString())) { + const txn = new Transaction({type: TransactionType.pay, from: from, to: from, amount: 1000, fee: sp.fee, ...sp}); + return { + txn: txn, + signer: makeBasicAccountTransactionSigner({addr: from, sk: undefined}) + }; + } + else { + return val; + } + }).filter((value) => value !== undefined && value !== "" && value !== null); + + console.log(methodArgs); atc.addMethodCall({ + ...appCallParams, method: new ABIMethod(this.method), - methodArgs: methodArgs, - ...appCallParams + methodArgs }); const unsignedTxns= atc.buildGroup(); diff --git a/src/packages/abi/types.ts b/src/packages/abi/types.ts index 826e1ba5..f306b21f 100644 --- a/src/packages/abi/types.ts +++ b/src/packages/abi/types.ts @@ -7,7 +7,7 @@ export interface A_Application_ABI { abi: ABIContractParams; } -export const ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES: ABITransactionType[] = [ABITransactionType.pay, ABITransactionType.axfer]; +export const ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES: ABITransactionType[] = [ABITransactionType.pay]; export interface A_ABI_METHOD_EXECUTOR_ARG { type: ABIArgumentType, From c2970946b81ae9fb68a65b87555e017616b92124 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 19 Nov 2022 00:53:55 +0530 Subject: [PATCH 49/86] support payment transaction in ABI executor --- src/components/LeftBar/LeftBar.scss | 3 + src/components/LeftBar/LeftBar.tsx | 4 +- .../ABIMethodExecutor/ABIMethodExecutor.scss | 9 +++ .../ABIMethodExecutor/ABIMethodExecutor.tsx | 71 +++++++++++++++++-- src/packages/abi/classes/ABIMethodExecutor.ts | 5 +- 5 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/components/LeftBar/LeftBar.scss b/src/components/LeftBar/LeftBar.scss index 88294809..75609180 100644 --- a/src/components/LeftBar/LeftBar.scss +++ b/src/components/LeftBar/LeftBar.scss @@ -29,6 +29,9 @@ } .bottom-menu-item-wrapper { + &:not(:last-child) { + margin: 5px 0; + } .bottom-menu-item-container { text-align: center; padding: 15px 0; diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index c9942dd8..1e2ab406 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -10,7 +10,7 @@ import {showSettings} from "../../redux/settings/actions/settings"; import Logo from '../../assets/images/logo-black.png'; import {useLocation, useNavigate} from "react-router-dom"; import {RootState} from "../../redux/store"; -import {shadedClr, shadedClr1, shadedClr2} from "../../utils/common"; +import {shadedClr, shadedClr1} from "../../utils/common"; import CodeIcon from '@mui/icons-material/Code'; import StorageIcon from '@mui/icons-material/Storage'; import GavelIcon from '@mui/icons-material/Gavel'; @@ -135,7 +135,7 @@ function LeftBar(): JSX.Element {
-
+
{wallet.information.address ?
diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss index 2bfa75c6..4408b4a3 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss @@ -39,6 +39,15 @@ } .abi-method-arg { margin: 15px 0; + .arg-transaction-wrapper { + .arg-transaction-container { + margin-top: 15px; + margin-bottom: 25px; + background: $color-grey-very-light; + padding: 15px; + border-radius: 10px; + } + } } .abi-method-execute { text-align: right; diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 71910e5c..a7cdb8a3 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -2,7 +2,7 @@ import './ABIMethodExecutor.scss'; import React, {useEffect, useState} from "react"; import { ABIMethod, - ABIMethodParams + ABIMethodParams, abiTypeIsTransaction, TransactionType } from "algosdk"; import { Button, @@ -67,6 +67,17 @@ const initialState: ABIMethodExecutorState = { executorArgs: [] }; +const formLabelSx = { + marginLeft: '5px', + fontSize: '13px', + fontWeight: 'bold', + color: theme.palette.grey[600] +}; + +const argTransactionSx = { + background: theme.palette.common.white.toString() +}; + function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.method, handleClose}: ABIMethodExecutorProps): JSX.Element { const wallet = useSelector((state: RootState) => state.wallet); @@ -197,8 +208,59 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
Arguments
{executorArgs.map((arg, index) => { return
- {`${arg.name} (${arg.type.toString()})`} - {`${arg.name} (${arg.type.toString()})`} + {abiTypeIsTransaction(arg.type.toString()) ?
+
+
+ {arg.type.toString() === TransactionType.pay ?
+ + To + { + const processedArgs = executorArgs; + processedArgs[index] = { + ...arg, + value: { + ...arg.value, + to: ev.target.value + } + }; + + setState(prevState => ({...prevState, executorArgs: processedArgs})); + }} + fullWidth/> + + + Amount + { + const processedArgs = executorArgs; + processedArgs[index] = { + ...arg, + value: { + ...arg.value, + amount: ev.target.value + } + }; + + setState(prevState => ({...prevState, executorArgs: processedArgs})); + }} + fullWidth/> + + +
: ''} +
+
+ +
: { @@ -210,7 +272,8 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth setState(prevState => ({...prevState, executorArgs: processedArgs})); }} - fullWidth/> + fullWidth/>} +
})}
diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 4e945015..94ca6473 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -3,7 +3,7 @@ import { ABIMethod, ABIMethodParams, ABITransactionType, - abiTypeIsTransaction, + abiTypeIsTransaction, algosToMicroalgos, AtomicTransactionComposer, makeBasicAccountTransactionSigner, Transaction, TransactionType, @@ -108,11 +108,10 @@ export default class ABIMethodExecutor { signer } - console.log(sp); const methodArgs = args.map((arg) => { const val = this.parseArgumentValue(arg); if (abiTypeIsTransaction(arg.type.toString())) { - const txn = new Transaction({type: TransactionType.pay, from: from, to: from, amount: 1000, fee: sp.fee, ...sp}); + const txn = new Transaction({type: TransactionType.pay, from: from, to: val.to, amount: algosToMicroalgos(val.amount), fee: sp.fee, ...sp}); return { txn: txn, signer: makeBasicAccountTransactionSigner({addr: from, sk: undefined}) From c471ea4fbfef285e2aee16e625e3a44a1bd8ca65 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 19 Nov 2022 02:26:16 +0530 Subject: [PATCH 50/86] support payment txn in abi method executor UI --- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 13 +- .../ABIMethodExecutor/ABIMethodExecutor.scss | 22 ++ .../ABIMethodExecutor/ABIMethodExecutor.tsx | 232 ++++++++++++++++-- src/packages/abi/classes/ABIMethodExecutor.ts | 51 +++- src/packages/abi/types.ts | 11 + 5 files changed, 294 insertions(+), 35 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 3855429e..a4b7f138 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -15,8 +15,8 @@ import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {Alert} from "@mui/lab"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {useDispatch, useSelector} from "react-redux"; -import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; import {RootState} from "../../../../redux/store"; +import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../../../../packages/abi/types"; type ABIMethodProps = { method: ABIMethodParams, @@ -72,20 +72,11 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen if (!new ABIMethodExecutorCls(method).canExecute()) { dispatch(showSnack({ severity: 'error', - message: 'Group transactions are not yet supported by Dappflow. It is on our roadmap.' + message: `Cannot execute.Only [${ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES.join(',')}] are supported` })); return; } - const appId = new ABIConfig().getAppId(); - - if (!appId) { - dispatch(showSnack({ - severity: 'error', - message: 'App ID is null. Before you execute please setup an App ID using the config button above.' - })); - return; - } setState(prevState => ({...prevState, showExecutor: true})); }} color={"primary"} diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss index 4408b4a3..de2525ba 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss @@ -22,6 +22,28 @@ min-height: 500px; border-right: 1px solid $color-grey-light; padding: 0 15px 0 0; + .abi-method-app-creation-wrapper { + .abi-method-app-creation-container { + .abi-method-app-creation-question { + font-size: 14px; + margin-top: 5px; + color: $color-grey-dark; + } + .abi-method-app-creation-form { + margin-top: 15px; + .teal-program { + font-size: 10px; + margin-top: 10px; + word-break: break-all; + background: $color-grey-very-light; + padding: 15px; + border-radius: 10px; + height: 30px; + overflow: auto; + } + } + } + } .abi-method-metadata { .metadata-item { font-size: 14px; diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index a7cdb8a3..5c525f39 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -5,7 +5,7 @@ import { ABIMethodParams, abiTypeIsTransaction, TransactionType } from "algosdk"; import { - Button, + Button, ButtonGroup, Dialog, DialogActions, DialogContent, @@ -19,13 +19,18 @@ import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {handleException} from "../../../../redux/common/actions/exception"; import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; -import {A_ABI_METHOD_EXECUTOR_ARG} from "../../../../packages/abi/types"; +import {A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, A_ABI_METHOD_EXECUTOR_ARG} from "../../../../packages/abi/types"; import CloseIcon from "@mui/icons-material/Close"; import {RootState} from "../../../../redux/store"; import dappflow from "../../../../utils/dappflow"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import {TransactionClient} from "../../../../packages/core-sdk/clients/transactionClient"; import {BaseTransaction} from "../../../../packages/core-sdk/transactions/baseTransaction"; +import {FileUploadOutlined} from "@mui/icons-material"; +import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; +import {getFileContent} from "../../../../packages/core-sdk/utils/fileUtils"; +import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicationClient"; +import {CoreTransaction} from "../../../../packages/core-sdk/classes/core/CoreTransaction"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -59,12 +64,25 @@ const defaultProps: ABIMethodExecutorProps = { interface ABIMethodExecutorState{ appId: string, - executorArgs: A_ABI_METHOD_EXECUTOR_ARG[] + executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], + creation: boolean, + creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS } const initialState: ABIMethodExecutorState = { appId: '', - executorArgs: [] + executorArgs: [], + creation: false, + creationParams: { + id: '', + approvalProgram: '', + clearProgram: '', + globalBytes: '', + localBytes: '', + globalInts: '', + localInts: '', + note: '' + }, }; const formLabelSx = { @@ -83,7 +101,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const wallet = useSelector((state: RootState) => state.wallet); const dispatch = useDispatch(); const [ - {appId, executorArgs}, + {appId, executorArgs, creation, creationParams}, setState ] = useState({ ...initialState @@ -105,8 +123,8 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth ...arg, value: '' }); - setState(prevState => ({...prevState, executorArgs: processedArgs, appId: new ABIConfig().getAppId()})); }); + setState(prevState => ({...prevState, executorArgs: processedArgs, appId: new ABIConfig().getAppId()})); }, [show]); @@ -119,18 +137,11 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth } async function execute() { - if (!appId) { - dispatch(showSnack({ - severity: 'error', - message: 'Invalid Application ID.' - })); - return; - } try { dispatch(showLoader('Signing transaction')); const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); - const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(Number(appId), wallet.information.address, executorArgs); + const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(appId ? Number(appId) : undefined, wallet.information.address, executorArgs, creation, creationParams); const signedTxns = await dappflow.signer.signGroupTxns(unsignedTxns.map((unsignedTxn) => { return unsignedTxn.txn; @@ -144,10 +155,17 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth dispatch(showLoader('Waiting for confirmation')); await txnInstance.waitForConfirmation(txId); - await new TransactionClient(dappflow.network).get(txId); + const txn = await new TransactionClient(dappflow.network).get(txId); dispatch(hideLoader()); handleClose(); + clearState(); + + if (creation) { + const txnInstance = new CoreTransaction(txn); + new ABIConfig().setAppId(txnInstance.getAppId().toString()); + } + dispatch(showSnack({ severity: 'success', message: 'Method executed successfully: ' + txId @@ -159,6 +177,28 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth } } + async function validateProgram(event): Promise { + let file = event.target.files[0]; + const target = event.target; + + try { + dispatch(showLoader('Reading TEAL program')); + const content = await getFileContent(file); + dispatch(hideLoader()); + + dispatch(showLoader('Compiling program')); + const compileResp = await new ApplicationClient(dappflow.network).compileProgram(content); + dispatch(hideLoader()); + + target.value = null; + return compileResp; + } + catch (e: any) { + dispatch(hideLoader()); + dispatch(handleException(e)); + } + } + return (
@@ -199,8 +239,168 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
-
+ {appId ?
Application ID : {appId} +
: ''} +
+
+
+
+ Do you want to use this method for app creation ? +
+ + + + + + + {creation ?
+
+
+ + + Global bytes + { + setState(prevState => ({...prevState, creationParams: { + ...creationParams, + globalBytes: ev.target.value + }})); + } + } + fullWidth/> + + + Global ints + { + setState(prevState => ({...prevState, creationParams: { + ...creationParams, + globalInts: ev.target.value + }})); + } + } + fullWidth/> + + + Local bytes + { + setState(prevState => ({...prevState, creationParams: { + ...creationParams, + localBytes: ev.target.value + }})); + } + } + fullWidth/> + + + Local ints + { + setState(prevState => ({...prevState, creationParams: { + ...creationParams, + localInts: ev.target.value + }})); + } + } + fullWidth/> + + + Approval program +
+ + {creationParams.approvalProgram ?
+ {creationParams.approvalProgram} +
: ''} + +
+
+ + + Clear program +
+ + {creationParams.clearProgram ?
+ {creationParams.clearProgram} +
: ''} + +
+
+ + + + + Note + { + setState(prevState => ({...prevState, creationParams: { + ...creationParams, + note: ev.target.value + }})); + } + } + fullWidth/> + + + +
+ +
+ + +
+
: ''} +
diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 94ca6473..dee1b682 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -9,9 +9,14 @@ import { TransactionType, TransactionWithSigner } from "algosdk"; -import {A_ABI_METHOD_EXECUTOR_ARG, ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../types"; +import { + A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, + A_ABI_METHOD_EXECUTOR_ARG, + ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES +} from "../types"; import dappflow from "../../../utils/dappflow"; import {BaseTransaction} from "../../core-sdk/transactions/baseTransaction"; +import {ApplicationTransaction} from "../../core-sdk/transactions/applicationTransaction"; export default class ABIMethodExecutor { method: ABIMethodParams @@ -94,24 +99,55 @@ export default class ABIMethodExecutor { return txnTypes; } - async getUnsignedTxns(appId: number, from: string, args: A_ABI_METHOD_EXECUTOR_ARG[] = []): Promise { - console.log(this.getSequenceOfTxnTypes()); + async getUnsignedTxns(appId: number, from: string, args: A_ABI_METHOD_EXECUTOR_ARG[] = [], isCreation: boolean = false, params: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS): Promise { + const appCallInstance = new ApplicationTransaction(dappflow.network); + const atc = new AtomicTransactionComposer(); const sp = await new BaseTransaction(dappflow.network).getSuggestedParams(); const signer = undefined; - const appCallParams = { + let appCallParams = { appID: appId, sender: from, - suggestedParams: sp, - signer + suggestedParams: { + ...sp + }, + signer, + numGlobalInts: undefined, + numGlobalByteSlices: undefined, + numLocalInts: undefined, + numLocalByteSlices: undefined, + approvalProgram: undefined, + clearProgram: undefined, + note: undefined + } + + if (isCreation) { + appCallParams.appID = 0; + appCallParams.numGlobalInts = Number(params.globalInts); + appCallParams.numGlobalByteSlices = Number(params.globalBytes); + appCallParams.numLocalInts = Number(params.localInts); + appCallParams.numLocalByteSlices = Number(params.localBytes); + appCallParams.approvalProgram = appCallInstance.getProgramBytes(params.approvalProgram); + appCallParams.clearProgram = appCallInstance.getProgramBytes(params.clearProgram); + appCallParams.note = appCallInstance.toUint8Array(params.note); } + else { + delete appCallParams.numGlobalByteSlices; + delete appCallParams.numGlobalInts; + delete appCallParams.numLocalInts; + delete appCallParams.numLocalByteSlices; + delete appCallParams.approvalProgram; + delete appCallParams.clearProgram; + } + + console.log(appCallParams); const methodArgs = args.map((arg) => { const val = this.parseArgumentValue(arg); if (abiTypeIsTransaction(arg.type.toString())) { - const txn = new Transaction({type: TransactionType.pay, from: from, to: val.to, amount: algosToMicroalgos(val.amount), fee: sp.fee, ...sp}); + const txn = new Transaction({type: TransactionType.pay, from: from, to: val.to, amount: algosToMicroalgos(val.amount), ...sp}); return { txn: txn, signer: makeBasicAccountTransactionSigner({addr: from, sk: undefined}) @@ -122,7 +158,6 @@ export default class ABIMethodExecutor { } }).filter((value) => value !== undefined && value !== "" && value !== null); - console.log(methodArgs); atc.addMethodCall({ ...appCallParams, diff --git a/src/packages/abi/types.ts b/src/packages/abi/types.ts index f306b21f..926728a5 100644 --- a/src/packages/abi/types.ts +++ b/src/packages/abi/types.ts @@ -14,4 +14,15 @@ export interface A_ABI_METHOD_EXECUTOR_ARG { name?: string, description?: string, value: any +} + +export interface A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS { + id: string, + approvalProgram: string, + clearProgram: string, + globalBytes: string, + localBytes: string, + globalInts: string, + localInts: string, + note: string } \ No newline at end of file From 4d999ad3916300894dff0a450f0d80edcb144895 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 19 Nov 2022 13:12:49 +0530 Subject: [PATCH 51/86] abi methos executor validations --- .../ABIMethodExecutor/ABIMethodExecutor.scss | 15 +++- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 76 ++++++++++++++++--- 2 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss index de2525ba..6686bfec 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.scss @@ -8,11 +8,17 @@ .abi-method-executor-modal-content { .abi-method-executor-header { + margin-bottom: 15px; + border-bottom: 1px solid $color-grey-light; + padding-bottom: 15px; + display: flex; + justify-content: space-between; .abi-method-name { font-family: PoppinsBold !important; - margin-bottom: 15px; - border-bottom: 1px solid $color-grey-light; - padding-bottom: 15px; + } + .abi-app-id { + font-size: 14px; + font-weight: bold; } } .abi-method-executor-body { @@ -88,6 +94,9 @@ text-align: center; font-size: 18px; } + .abi-method-result-body { + margin-top: 25px; + } } } } diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 5c525f39..b4c80300 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -5,6 +5,7 @@ import { ABIMethodParams, abiTypeIsTransaction, TransactionType } from "algosdk"; import { + Alert, Button, ButtonGroup, Dialog, DialogActions, @@ -31,6 +32,7 @@ import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/typ import {getFileContent} from "../../../../packages/core-sdk/utils/fileUtils"; import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicationClient"; import {CoreTransaction} from "../../../../packages/core-sdk/classes/core/CoreTransaction"; +import {isNumber} from "../../../../utils/common"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -66,7 +68,8 @@ interface ABIMethodExecutorState{ appId: string, executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], creation: boolean, - creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS + creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, + error: string } const initialState: ABIMethodExecutorState = { @@ -83,6 +86,7 @@ const initialState: ABIMethodExecutorState = { localInts: '', note: '' }, + error: '' }; const formLabelSx = { @@ -101,7 +105,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const wallet = useSelector((state: RootState) => state.wallet); const dispatch = useDispatch(); const [ - {appId, executorArgs, creation, creationParams}, + {appId, executorArgs, creation, creationParams, error}, setState ] = useState({ ...initialState @@ -136,12 +140,53 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth ev.stopPropagation(); } + function setError(msg: string) { + setState(prevState => ({...prevState, error: msg})); + } + async function execute() { + setError(""); + + if (creation) { + const {globalBytes, globalInts, localInts, localBytes, approvalProgram, clearProgram} = creationParams; + + if (!globalBytes || !isNumber(globalBytes)) { + setError('Invalid global bytes'); + return; + } + if (!globalInts || !isNumber(globalInts)) { + setError('Invalid global ints'); + return; + } + if (!localBytes || !isNumber(localBytes)) { + setError('Invalid local bytes'); + return; + } + if (!localInts || !isNumber(localInts)) { + setError('Invalid local ints'); + return; + } + if (!approvalProgram) { + setError('Invalid approval program'); + return; + } + if (!clearProgram) { + setError('Invalid clear program'); + return; + } + } + else { + if (!appId) { + setError('Invalid app id'); + return; + } + } + try { dispatch(showLoader('Signing transaction')); const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); - const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(appId ? Number(appId) : undefined, wallet.information.address, executorArgs, creation, creationParams); + const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(creation ? undefined : Number(appId) , wallet.information.address, executorArgs, creation, creationParams); const signedTxns = await dappflow.signer.signGroupTxns(unsignedTxns.map((unsignedTxn) => { return unsignedTxn.txn; @@ -173,7 +218,8 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth } catch (e: any) { dispatch(hideLoader()); - dispatch(handleException(e)); + setError(e.message); + //dispatch(handleException(e)); } } @@ -231,6 +277,11 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
{abiMethodInstance.name}
+
+ {!creation && appId ?
+ APP ID : {appId} +
: ''} +
@@ -239,9 +290,6 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
- {appId ?
- Application ID : {appId} -
: ''}
@@ -249,7 +297,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth Do you want to use this method for app creation ?
- + @@ -321,7 +369,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth variant="outlined" component="label" size={"small"} - color={"warning"}> + color={"primary"}> Upload + color={"primary"}> Upload
-
Arguments
+ {executorArgs.length > 0 ?
Arguments
: ''} + {executorArgs.map((arg, index) => { return
{`${arg.name} (${arg.type.toString()})`} @@ -502,6 +551,11 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
Result
+
+ {error ?
+ {error} +
: ''} +
From 55288654f066f4468ca04f4b12ff7b205bd1c205 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 19 Nov 2022 14:05:43 +0530 Subject: [PATCH 52/86] show method exector results --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index b4c80300..7005d1f6 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -17,7 +17,6 @@ import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {theme} from "../../../../theme"; import {useDispatch, useSelector} from "react-redux"; import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; -import {showSnack} from "../../../../redux/common/actions/snackbar"; import {handleException} from "../../../../redux/common/actions/exception"; import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; import {A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, A_ABI_METHOD_EXECUTOR_ARG} from "../../../../packages/abi/types"; @@ -27,7 +26,7 @@ import dappflow from "../../../../utils/dappflow"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import {TransactionClient} from "../../../../packages/core-sdk/clients/transactionClient"; import {BaseTransaction} from "../../../../packages/core-sdk/transactions/baseTransaction"; -import {FileUploadOutlined} from "@mui/icons-material"; +import {Error, FileUploadOutlined} from "@mui/icons-material"; import {CompileResponse} from "algosdk/dist/types/src/client/v2/algod/models/types"; import {getFileContent} from "../../../../packages/core-sdk/utils/fileUtils"; import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicationClient"; @@ -69,7 +68,8 @@ interface ABIMethodExecutorState{ executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], creation: boolean, creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, - error: string + error: string, + success: string } const initialState: ABIMethodExecutorState = { @@ -86,7 +86,8 @@ const initialState: ABIMethodExecutorState = { localInts: '', note: '' }, - error: '' + error: '', + success: '' }; const formLabelSx = { @@ -105,7 +106,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const wallet = useSelector((state: RootState) => state.wallet); const dispatch = useDispatch(); const [ - {appId, executorArgs, creation, creationParams, error}, + {appId, executorArgs, creation, creationParams, error, success}, setState ] = useState({ ...initialState @@ -140,13 +141,22 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth ev.stopPropagation(); } + function resetResult() { + setError(""); + setSuccess(""); + } + function setError(msg: string) { setState(prevState => ({...prevState, error: msg})); } + function setSuccess(msg: string) { + setState(prevState => ({...prevState, success: msg})); + } + async function execute() { - setError(""); + resetResult(); if (creation) { const {globalBytes, globalInts, localInts, localBytes, approvalProgram, clearProgram} = creationParams; @@ -203,18 +213,12 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth const txn = await new TransactionClient(dappflow.network).get(txId); dispatch(hideLoader()); - handleClose(); - clearState(); - if (creation) { const txnInstance = new CoreTransaction(txn); new ABIConfig().setAppId(txnInstance.getAppId().toString()); } - dispatch(showSnack({ - severity: 'success', - message: 'Method executed successfully: ' + txId - })); + setSuccess('Method executed successfully : ' + txId); } catch (e: any) { dispatch(hideLoader()); @@ -553,8 +557,21 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth
{error ?
- {error} + } color={"warning"} sx={{wordBreak: "break-word"}}>{error}
: ''} + + {success ?
+ +
+
+ {success} +
+
+ {/**/} +
+ +
: ''} +
From a4635861920db037ddc201c7585cd679cd0eeca8 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 19 Nov 2022 14:32:04 +0530 Subject: [PATCH 53/86] view connected account in explorer --- src/components/LeftBar/LeftBar.scss | 4 +--- src/components/LeftBar/LeftBar.tsx | 15 +++++++++++++++ .../Modules/AppManager/CreateApp/CreateApp.tsx | 4 ++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/components/LeftBar/LeftBar.scss b/src/components/LeftBar/LeftBar.scss index 75609180..665c7e2b 100644 --- a/src/components/LeftBar/LeftBar.scss +++ b/src/components/LeftBar/LeftBar.scss @@ -29,12 +29,10 @@ } .bottom-menu-item-wrapper { - &:not(:last-child) { - margin: 5px 0; - } .bottom-menu-item-container { text-align: center; padding: 15px 0; + border-top: 1px solid $color-grey; .small-text { font-size: 12px; white-space: nowrap; diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index 1e2ab406..d22354c9 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -25,6 +25,7 @@ import {logOut} from "../../redux/wallet/actions/wallet"; import LogoutIcon from '@mui/icons-material/Logout'; import SwapCallsIcon from '@mui/icons-material/SwapCalls'; import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; +import VisibilityIcon from '@mui/icons-material/Visibility'; function LeftBar(): JSX.Element { @@ -187,6 +188,20 @@ function LeftBar(): JSX.Element { Disconnect + { + navigate('/explorer/account/' + wallet.information.address); + closeWalletMenu(); + e.preventDefault(); + e.stopPropagation(); + } + }> + + + + View in explorer +
: + + + + + + + { + debounce(() => { + setState(prevState => ({...prevState, searchText: ev.target.value})); + }, 1000)(); + }} + fullWidth/> + + + + {searching ?
+ +
searching ...
+
:
+ + {assets.length === 0 ?
+ No results found +
:
+ {assets.map((asset) => { + return (
{ + onPick(asset); + clearState(); + }}> + {asset.params.name} +
ID: {asset.index}
+
); + })} +
} + +
} + +
+ + + + +
+ +
+
+
+ + : ''} +
); +} + +export default AssetPicker; diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 4bea21fb..a8fe100b 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -19,6 +19,7 @@ import { import dappflow from "../../../utils/dappflow"; import {BaseTransaction} from "../../core-sdk/transactions/baseTransaction"; import {ApplicationTransaction} from "../../core-sdk/transactions/applicationTransaction"; +import {CoreAsset} from "../../core-sdk/classes/core/CoreAsset"; export default class ABIMethodExecutor { method: ABIMethodParams @@ -103,8 +104,6 @@ export default class ABIMethodExecutor { async getUnsignedTxns(appId: number, from: string, args: A_ABI_METHOD_EXECUTOR_ARG[] = [], isCreation: boolean = false, params: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS): Promise { const appCallInstance = new ApplicationTransaction(dappflow.network); - - console.log(args); const atc = new AtomicTransactionComposer(); const sp = await new BaseTransaction(dappflow.network).getSuggestedParams(); @@ -154,13 +153,14 @@ export default class ABIMethodExecutor { const methodArgs = args.map((arg) => { const val = this.parseArgumentValue(arg); const argType = arg.type.toString() as TransactionType; + console.log(val); if (abiTypeIsTransaction(argType)) { let txn; if (argType === TransactionType.pay) { txn = new Transaction({type: TransactionType.pay, from: from, to: val.to, amount: algosToMicroalgos(val.amount), ...sp}); } else if (argType === TransactionType.axfer) { - txn = new Transaction({type: TransactionType.axfer, assetIndex: Number(val.assetId), from: from, to: val.to, amount: algosToMicroalgos(val.amount), ...sp}); + txn = new Transaction({type: TransactionType.axfer, assetIndex: Number(val.assetId), from: from, to: val.to, amount: new CoreAsset(val.asset).getAmountInDecimals(Number(val.amount)), ...sp}); } return { @@ -173,8 +173,6 @@ export default class ABIMethodExecutor { } }).filter((value) => value !== undefined && value !== "" && value !== null); - - console.log(methodArgs); atc.addMethodCall({ ...appCallParams, method: new ABIMethod(this.method), diff --git a/src/packages/core-sdk/clients/assetClient.ts b/src/packages/core-sdk/clients/assetClient.ts index 516bf36d..6d1d1d39 100644 --- a/src/packages/core-sdk/clients/assetClient.ts +++ b/src/packages/core-sdk/clients/assetClient.ts @@ -50,4 +50,14 @@ export class AssetClient{ const response = await req.do(); return response as A_AssetTransactionsResponse; } + + async searchForAssetsByName(searchText: string): Promise { + return await this.indexer.searchForAssets().name(searchText).do() as A_Asset; + } + + async searchForAssetsByIndex(id: number): Promise { + return await this.indexer.searchForAssets().index(id).do() as A_Asset; + } + + } \ No newline at end of file diff --git a/src/packages/core-sdk/utils/common.ts b/src/packages/core-sdk/utils/common.ts new file mode 100644 index 00000000..c142698f --- /dev/null +++ b/src/packages/core-sdk/utils/common.ts @@ -0,0 +1,21 @@ +export function debounce (task: any, ms: number) { + let t = { promise: null, cancel: _ => void 0 } + return async (...args: any) => { + try { + // @ts-ignore + t.cancel() + t = deferred(ms) + await t.promise + await task(...args) + } + catch (_) { /* prevent memory leak */ } + } +} + +export function deferred (ms: number) { + let cancel, promise = new Promise((resolve, reject) => { + cancel = reject + setTimeout(resolve, ms) + }) + return { promise, cancel } +} \ No newline at end of file From 111710d65014309aa91b155262057f43040f3e10 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 23 Nov 2022 23:21:24 +0530 Subject: [PATCH 60/86] app creation failing bug fix --- src/components/Modules/AppManager/CreateApp/CreateApp.tsx | 2 +- src/packages/abi/classes/ABIMethodExecutor.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 55724fe1..ae88d29a 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -211,7 +211,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n appIndex: 0, appLocalByteSlices: Number(localBytes), appLocalInts: Number(localInts), - appOnComplete: onComplete as unknown as OnApplicationComplete, + appOnComplete: Number(onComplete) as unknown as OnApplicationComplete, boxes: [], extraPages: Number(extraPages), fee: 0, diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index a8fe100b..4dbd8811 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -137,7 +137,7 @@ export default class ABIMethodExecutor { appCallParams.clearProgram = appCallInstance.getProgramBytes(params.clearProgram); appCallParams.note = appCallInstance.toUint8Array(params.note); appCallParams.extraPages = Number(params.extraPages); - appCallParams.onComplete = params.onComplete; + appCallParams.onComplete = Number(params.onComplete); } else { delete appCallParams.numGlobalByteSlices; @@ -153,7 +153,7 @@ export default class ABIMethodExecutor { const methodArgs = args.map((arg) => { const val = this.parseArgumentValue(arg); const argType = arg.type.toString() as TransactionType; - console.log(val); + if (abiTypeIsTransaction(argType)) { let txn; if (argType === TransactionType.pay) { From 99c73eb46086ecb6b06031bcc2059b08c64cd044 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 30 Nov 2022 14:24:41 +0400 Subject: [PATCH 61/86] type conversion issues --- .../LeftBar/ConnectWallet/ConnectWallet.scss | 3 +- src/components/LeftBar/LeftBar.tsx | 40 +++++++++---------- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 7 ++-- .../Modules/ABI/ABIStudio/ABIStudio.tsx | 2 +- .../Modules/ABI/ImportABI/ImportABI.tsx | 7 ++++ .../AppCallTransaction/AppCallTransaction.tsx | 2 +- .../AppCallTxnArguments.tsx | 17 ++++---- src/packages/abi/classes/ABIMethodExecutor.ts | 3 ++ .../core-sdk/classes/core/CoreAppCall.ts | 3 ++ 9 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/components/LeftBar/ConnectWallet/ConnectWallet.scss b/src/components/LeftBar/ConnectWallet/ConnectWallet.scss index 1423c61c..16a5c048 100644 --- a/src/components/LeftBar/ConnectWallet/ConnectWallet.scss +++ b/src/components/LeftBar/ConnectWallet/ConnectWallet.scss @@ -100,8 +100,7 @@ border: 1px solid $color-grey-light; &:hover { cursor: pointer; - background: $color-dark; - color: $color-light; + border-color: $color-dark; } } } diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index 7f069d73..792482fe 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -164,43 +164,43 @@ function LeftBar(): JSX.Element { { - dispatch(showConnectWallet()); - closeWalletMenu(); - e.preventDefault(); - e.stopPropagation(); - } - }> + navigate('/explorer/account/' + wallet.information.address); + closeWalletMenu(); + e.preventDefault(); + e.stopPropagation(); + } + }> - + - Switch wallet + View in explorer { - dispatch(logOut()); - closeWalletMenu(); - e.preventDefault(); - e.stopPropagation(); - }}> + dispatch(showConnectWallet()); + closeWalletMenu(); + e.preventDefault(); + e.stopPropagation(); + } + }> - + - Disconnect + Switch wallet { - navigate('/explorer/account/' + wallet.information.address); + dispatch(logOut()); closeWalletMenu(); e.preventDefault(); e.stopPropagation(); - } - }> + }}> - + - View in explorer + Disconnect diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 244288fa..004a4553 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -16,7 +16,8 @@ type ABIEditorProps = { abi: ABIContractParams, hideNetworks?: boolean, supportExecutor?: boolean, - supportCreateApp?: boolean + supportCreateApp?: boolean, + supportConfig?: boolean }; interface ABIEditorState{ @@ -29,7 +30,7 @@ const initialState: ABIEditorState = { showCreateApp: false }; -function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false, supportCreateApp = false}: ABIEditorProps): JSX.Element { +function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false, supportCreateApp = false, supportConfig = false}: ABIEditorProps): JSX.Element { const abiInstance = new ABIContract(abi); const networks = abiInstance.networks; @@ -60,7 +61,7 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support
- {supportExecutor ?
+ {supportConfig ?
diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.tsx b/src/components/Modules/ABI/ImportABI/ImportABI.tsx index 745dc3c9..102378fe 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.tsx +++ b/src/components/Modules/ABI/ImportABI/ImportABI.tsx @@ -171,6 +171,13 @@ function ImportABI(props): JSX.Element { sx={{marginLeft: '10px'}} > + { + setState(prevState => ({...prevState, url: "https://raw.githubusercontent.com/jasonpaulos/decipher-22-pyteal-talk/main/contract/contract.json"})); + }} label="Poll ABI" size="small" color={"warning"} variant={"outlined"} + sx={{marginLeft: '10px'}} + > + +
diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/AppCallTransaction.tsx b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/AppCallTransaction.tsx index 26efd558..b85a538a 100644 --- a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/AppCallTransaction.tsx +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/AppCallTransaction.tsx @@ -104,7 +104,7 @@ function AppCallTransaction(props): JSX.Element { {txnInstance.hasAppCallArguments() ?
- +
: ''} diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx index 87b46f84..327e1f75 100644 --- a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx @@ -1,11 +1,15 @@ import './AppCallTxnArguments.scss'; import React, {useEffect, useState} from "react"; -import {A_SearchTransaction_App_Call_Payload} from "../../../../../../../../../packages/core-sdk/types"; +import { + A_SearchTransaction, + A_SearchTransaction_App_Call_Payload +} from "../../../../../../../../../packages/core-sdk/types"; import {Alert, Button, ButtonGroup, Grid, Typography} from "@mui/material"; import {ApplicationABI} from "../../../../../../../../../packages/abi/classes/ApplicationABI"; import {CoreAppCall} from "../../../../../../../../../packages/core-sdk/classes/core/CoreAppCall"; import {ABIContractParams} from "algosdk"; import ABIMethodSignature from "../../../../../../../ABI/ABIMethodSignature/ABIMethodSignature"; +import {CoreTransaction} from "../../../../../../../../../packages/core-sdk/classes/core/CoreTransaction"; interface AppCallTxnArgumentsState{ textEncoding: string, @@ -20,22 +24,21 @@ const initialState: AppCallTxnArgumentsState = { function AppCallTxnArguments(props): JSX.Element { - const appCallPayload: A_SearchTransaction_App_Call_Payload = props.appCallPayload; + const transaction: A_SearchTransaction = props.transaction; + const txnInstance = new CoreTransaction(transaction); + const appCallPayload: A_SearchTransaction_App_Call_Payload = txnInstance.getAppCallPayload(); const callInstance = new CoreAppCall(appCallPayload); const args = callInstance.getAppCallArguments(); - const isCreate = callInstance.isCreate(); useEffect(() => { async function loadABI() { - const abiDetails = await new ApplicationABI().get(appCallPayload['application-id']); + const abiDetails = await new ApplicationABI().get(txnInstance.getAppId()); if (abiDetails) { setState(prevState => ({...prevState, abi: abiDetails.abi, showEncoding: true})); } } - if (!isCreate) { - loadABI(); - } + loadABI(); }, []); const [ {textEncoding, showEncoding, abi}, diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 4dbd8811..6cedca11 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -71,6 +71,7 @@ export default class ABIMethodExecutor { switch (dataType) { case "uint64": + case "uint8": case "byte": case "asset": case "application": @@ -79,6 +80,8 @@ export default class ABIMethodExecutor { return Boolean(val); case "byte[]": return new Uint8Array(Buffer.from(val, "base64")); + case "string[7]": + return val.split(','); default: return val; } diff --git a/src/packages/core-sdk/classes/core/CoreAppCall.ts b/src/packages/core-sdk/classes/core/CoreAppCall.ts index 0df1abfe..7273d056 100644 --- a/src/packages/core-sdk/classes/core/CoreAppCall.ts +++ b/src/packages/core-sdk/classes/core/CoreAppCall.ts @@ -116,6 +116,9 @@ export class CoreAppCall { try { decodedArg.decodedValue = typeToDecode.decode(encodedArg); decodedArg.decoded = true; + if (type === 'bool') { + decodedArg.decodedValue = decodedArg.decodedValue.toString(); + } } catch (e) { decodedArg.decodedValue = txnArg; From 8f0eaf42f012bb52029d63f405f520dbe5d730e0 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 6 Dec 2022 19:09:11 +0530 Subject: [PATCH 62/86] Pera Wallet integration --- src/packages/abi/classes/ABIMethodExecutor.ts | 7 +- src/packages/signers/adapter.ts | 11 +++ src/packages/signers/constants/index.ts | 3 +- src/packages/signers/peraWalletSigner.ts | 68 +++++++++++++++++++ 4 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 src/packages/signers/peraWalletSigner.ts diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 6cedca11..61fccdcc 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -70,8 +70,10 @@ export default class ABIMethodExecutor { const val = arg.value; switch (dataType) { - case "uint64": case "uint8": + case "uint16": + case "uint32": + case "uint64": case "byte": case "asset": case "application": @@ -179,7 +181,8 @@ export default class ABIMethodExecutor { atc.addMethodCall({ ...appCallParams, method: new ABIMethod(this.method), - methodArgs + methodArgs, + //boxes: [{appIndex: 0, name: decodeAddress('R34NJOSWMTL2EQ4UFXW7Q2L4COUMRN4I6GG55L2NGADVDFVFJXAUFQU7CA').publicKey }] }); const unsignedTxns= atc.buildGroup(); diff --git a/src/packages/signers/adapter.ts b/src/packages/signers/adapter.ts index 3afe2c7b..172df32c 100644 --- a/src/packages/signers/adapter.ts +++ b/src/packages/signers/adapter.ts @@ -4,11 +4,13 @@ import {WalletSigner} from "./walletSigner"; import {BrowserAlgoSigner} from "./algoSigner"; import {LogicSigner} from "./logicSigner"; import {MyAlgoWalletSigner} from "./myAlgoWalletSigner"; +import {PeraWalletSigner} from "./peraWalletSigner"; const ws = new WalletSigner(); const as = new BrowserAlgoSigner(); const ls = new LogicSigner(); const maws = new MyAlgoWalletSigner(); +const ps = new PeraWalletSigner(); export function getSigner(name: string): Signer{ if (name === SIGNERS.WALLET) { @@ -23,6 +25,9 @@ export function getSigner(name: string): Signer{ else if (name === SIGNERS.MY_ALGO_WALLET) { return maws; } + else if (name === SIGNERS.PERA_WALLET) { + return ps; + } return ws; } @@ -47,6 +52,12 @@ export function getSupportedSigners(): SupportedSigner[] { label: 'MyAlgo Wallet', instance: getSigner(SIGNERS.MY_ALGO_WALLET), logo: 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMCIgaGVpZ2h0PSIzMCIgdmlld0JveD0iMCAwIDMwIDMwIj4KICAgIDxwYXRoIGlkPSJwcmVmaXhfX1N1YnRyYWN0aW9uXzExIiBmaWxsPSIjMjQ1ZWM3IiBkPSJNMTUgMzBBMTUgMTUgMCAwIDEgNC4zOTIgNC4zOTMgMTUgMTUgMCAxIDEgMjUuNiAyNS42MDYgMTQuOSAxNC45IDAgMCAxIDE1IDMwem0zLjk5MS0xOS41MDhsLjEyMi40NjggMi40NTkgOC45MWgyTDIwLjIxNCA4LjMxNCAyMC4xMzIgOGgtMS43NDVsLS4wNC4wNjMtMS42MzMgMi45LTEuNjc0IDIuOTc0LS4wNC4wNzEtLjAxOS0uMDcxLS4yLS43NjQtLjU3MS0yLjIxLS4wNjEtLjIyLS42MzMtMi40MjlMMTMuNDMgOGgtMS43NDVsLS4wNDEuMDYzLTEuNjMzIDIuOS0xLjY3MyAyLjk3NEw2LjY3MyAxNi45IDUgMTkuODczaDJMOC42NzQgMTYuOWwxLjY3NC0yLjk2MyAxLjY2My0yLjk3NC4yNzUtLjQ3MS4xMjIuNDcxLjUxIDEuOTU4LjYzNCAyLjQzOS4yMi44MzItLjQuNzA3LTEuNjcyIDIuOTc0aDJsLjcwNy0xLjI1NSAxLjIyOC0yLjE3OSAxLjQxNC0yLjUgMS42NjMtMi45NzQuMjc0LS40Njl6IiBkYXRhLW5hbWU9IlN1YnRyYWN0aW9uIDExIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSguMDAyKSIvPgo8L3N2Zz4K' + }, + { + name: SIGNERS.PERA_WALLET, + label: 'Pera Wallet', + instance: getSigner(SIGNERS.PERA_WALLET), + logo: 'data:image/png;base64,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' } ]; } \ No newline at end of file diff --git a/src/packages/signers/constants/index.ts b/src/packages/signers/constants/index.ts index e78c4a60..95980e0d 100644 --- a/src/packages/signers/constants/index.ts +++ b/src/packages/signers/constants/index.ts @@ -2,7 +2,8 @@ export enum SIGNERS { WALLET = 'wallet', ALGO_SIGNER = 'algo_signer', LOGIC_SIG = 'logic_sig', - MY_ALGO_WALLET = 'my_algo_wallet' + MY_ALGO_WALLET = 'my_algo_wallet', + PERA_WALLET = 'pera_wallet' } export enum ALGO_SIGNER_NET { diff --git a/src/packages/signers/peraWalletSigner.ts b/src/packages/signers/peraWalletSigner.ts new file mode 100644 index 00000000..ed401660 --- /dev/null +++ b/src/packages/signers/peraWalletSigner.ts @@ -0,0 +1,68 @@ +import {Signer, SignerAccount} from "./types"; +import {Transaction} from "algosdk"; +import {NETWORKS} from "../core-sdk/constants"; +import {PeraWalletConnect} from '@perawallet/connect'; +import {PeraWalletNetwork} from "@perawallet/connect/dist/util/peraWalletTypes"; + + +export class PeraWalletSigner implements Signer{ + private supportedNetworks: string[]; + private peraWallet: PeraWalletConnect; + + constructor() { + this.peraWallet = new PeraWalletConnect(); + this.supportedNetworks = [NETWORKS.TESTNET, NETWORKS.MAINNET]; + } + + async signTxn(unsignedTxn: Transaction): Promise { + const signedTxn = await this.peraWallet.signTransaction([[{txn: unsignedTxn}]]); + return signedTxn[0]; + } + + async signGroupTxns(unsignedTxns: Transaction[]): Promise { + const encodedTransactionObjs = []; + unsignedTxns.forEach((unsignedTxn) => { + encodedTransactionObjs.push({txn: unsignedTxn}); + }); + + const signedTxns = await this.peraWallet.signTransaction([encodedTransactionObjs]); + return signedTxns; + } + + async connect(name: string): Promise { + if (this.isInstalled()) { + if (this.isNetworkSupported(name)) { + const accounts: SignerAccount[] = []; + const wallets = await this.peraWallet.connect({network: name as PeraWalletNetwork}); + if (wallets) { + wallets.forEach((wallet) => { + accounts.push({ + address: wallet, + name: wallet + }); + }); + } + + return accounts; + } + else { + throw new Error(name + " is not supported by Pera Wallet"); + } + } + else { + throw new Error("Pera Wallet is not installed"); + } + } + + isInstalled(): boolean { + return true; + } + + isNetworkSupported(name: string): boolean { + return this.supportedNetworks.indexOf(name) !== -1; + } + + logout() { + this.peraWallet.disconnect(); + } +} \ No newline at end of file From a2f30850909131ffd2fef170f6f7c71de97f81b6 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 6 Dec 2022 19:39:27 +0530 Subject: [PATCH 63/86] package json peraconnect --- package.json | 1 + yarn.lock | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 250 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3d165b5d..346a3abb 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "@mui/lab": "^5.0.0-alpha.88", "@mui/material": "^5.6.0", "@mui/x-data-grid": "^5.8.0", + "@perawallet/connect": "^1.0.7", "@randlabs/myalgo-connect": "^1.4.0", "@reduxjs/toolkit": "^1.8.1", "@testing-library/jest-dom": "^5.14.1", diff --git a/yarn.lock b/yarn.lock index c6770e12..233a94e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1671,6 +1671,21 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@json-rpc-tools/types@^1.7.6": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@json-rpc-tools/types/-/types-1.7.6.tgz#5abd5fde01364a130c46093b501715bcce5bdc0e" + integrity sha512-nDSqmyRNEqEK9TZHtM15uNnDljczhCUdBmRhpNZ95bIPKEDQ+nTDmGMFd2lLin3upc5h2VVVd9tkTDdbXUhDIQ== + dependencies: + keyvaluestorage-interface "^1.0.0" + +"@json-rpc-tools/utils@^1.7.6": + version "1.7.6" + resolved "https://registry.yarnpkg.com/@json-rpc-tools/utils/-/utils-1.7.6.tgz#67f04987dbaa2e7adb6adff1575367b75a9a9ba1" + integrity sha512-HjA8x/U/Q78HRRe19yh8HVKoZ+Iaoo3YZjakJYxR+rw52NHo6jM+VE9b8+7ygkCFXl/EHID5wh/MkXaE/jGyYw== + dependencies: + "@json-rpc-tools/types" "^1.7.6" + "@pedrouid/environment" "^1.0.1" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.3" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.3.tgz#0300943770e04231041a51bd39f0439b5c7ab4f0" @@ -2144,6 +2159,24 @@ "@octokit/webhooks-types" "6.2.4" aggregate-error "^3.1.0" +"@pedrouid/environment@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@pedrouid/environment/-/environment-1.0.1.tgz#858f0f8a057340e0b250398b75ead77d6f4342ec" + integrity sha512-HaW78NszGzRZd9SeoI3JD11JqY+lubnaOx7Pewj5pfjqWXOEATpeKIFb9Z4t2WBUK2iryiXX3lzWwmYWgUL0Ug== + +"@perawallet/connect@^1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@perawallet/connect/-/connect-1.0.7.tgz#f825109ff78112ab36371f6215fd10f524464508" + integrity sha512-02ANpMGz0axS/BHBK5T44OoNS3sVITwOLrsle/bLg6fC7yFzM7Slsa0A/y+QiOutT0d8gXFKV3GVDYA3kBbXbg== + dependencies: + "@json-rpc-tools/utils" "^1.7.6" + "@walletconnect/client" "^1.8.0" + "@walletconnect/types" "^1.8.0" + bowser "^2.11.0" + buffer "^6.0.3" + lottie-web "^5.9.6" + qr-code-styling "^1.6.0-rc.1" + "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": version "0.5.5" resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz#e77aac783bd079f548daa0a7f080ab5b5a9741ca" @@ -2969,6 +3002,151 @@ "@typescript-eslint/types" "5.18.0" eslint-visitor-keys "^3.0.0" +"@walletconnect/browser-utils@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.8.0.tgz#33c10e777aa6be86c713095b5206d63d32df0951" + integrity sha512-Wcqqx+wjxIo9fv6eBUFHPsW1y/bGWWRboni5dfD8PtOmrihrEpOCmvRJe4rfl7xgJW8Ea9UqKEaq0bIRLHlK4A== + dependencies: + "@walletconnect/safe-json" "1.0.0" + "@walletconnect/types" "^1.8.0" + "@walletconnect/window-getters" "1.0.0" + "@walletconnect/window-metadata" "1.0.0" + detect-browser "5.2.0" + +"@walletconnect/client@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/client/-/client-1.8.0.tgz#6f46b5499c7c861c651ff1ebe5da5b66225ca696" + integrity sha512-svyBQ14NHx6Cs2j4TpkQaBI/2AF4+LXz64FojTjMtV4VMMhl81jSO1vNeg+yYhQzvjcGH/GpSwixjyCW0xFBOQ== + dependencies: + "@walletconnect/core" "^1.8.0" + "@walletconnect/iso-crypto" "^1.8.0" + "@walletconnect/types" "^1.8.0" + "@walletconnect/utils" "^1.8.0" + +"@walletconnect/core@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.8.0.tgz#6b2748b90c999d9d6a70e52e26a8d5e8bfeaa81e" + integrity sha512-aFTHvEEbXcZ8XdWBw6rpQDte41Rxwnuk3SgTD8/iKGSRTni50gI9S3YEzMj05jozSiOBxQci4pJDMVhIUMtarw== + dependencies: + "@walletconnect/socket-transport" "^1.8.0" + "@walletconnect/types" "^1.8.0" + "@walletconnect/utils" "^1.8.0" + +"@walletconnect/crypto@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@walletconnect/crypto/-/crypto-1.0.3.tgz#7b8dd4d7e2884fe3543c7c07aea425eef5ef9dd4" + integrity sha512-+2jdORD7XQs76I2Odgr3wwrtyuLUXD/kprNVsjWRhhhdO9Mt6WqVzOPu0/t7OHSmgal8k7SoBQzUc5hu/8zL/g== + dependencies: + "@walletconnect/encoding" "^1.0.2" + "@walletconnect/environment" "^1.0.1" + "@walletconnect/randombytes" "^1.0.3" + aes-js "^3.1.2" + hash.js "^1.1.7" + tslib "1.14.1" + +"@walletconnect/encoding@^1.0.1", "@walletconnect/encoding@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/encoding/-/encoding-1.0.2.tgz#cb3942ad038d6a6bf01158f66773062dd25724da" + integrity sha512-CrwSBrjqJ7rpGQcTL3kU+Ief+Bcuu9PH6JLOb+wM6NITX1GTxR/MfNwnQfhLKK6xpRAyj2/nM04OOH6wS8Imag== + dependencies: + is-typedarray "1.0.0" + tslib "1.14.1" + typedarray-to-buffer "3.1.5" + +"@walletconnect/environment@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7" + integrity sha512-T426LLZtHj8e8rYnKfzsw1aG6+M0BT1ZxayMdv/p8yM0MU+eJDISqNY3/bccxRr4LrF9csq02Rhqt08Ibl0VRg== + dependencies: + tslib "1.14.1" + +"@walletconnect/iso-crypto@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/iso-crypto/-/iso-crypto-1.8.0.tgz#44ddf337c4f02837c062dbe33fa7ab36789df451" + integrity sha512-pWy19KCyitpfXb70hA73r9FcvklS+FvO9QUIttp3c2mfW8frxgYeRXfxLRCIQTkaYueRKvdqPjbyhPLam508XQ== + dependencies: + "@walletconnect/crypto" "^1.0.2" + "@walletconnect/types" "^1.8.0" + "@walletconnect/utils" "^1.8.0" + +"@walletconnect/jsonrpc-types@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.2.tgz#b79519f679cd6a5fa4a1bea888f27c1916689a20" + integrity sha512-CZe8tjJX73OWdHjrBHy7HtAapJ2tT0Q3TYhPBhRxi3643lwPIQWC9En45ldY14TZwgSewkbZ0FtGBZK0G7Bbyg== + dependencies: + keyvaluestorage-interface "^1.0.0" + tslib "1.14.1" + +"@walletconnect/jsonrpc-utils@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.4.tgz#2009ba3907b02516f2caacd2fb871ff0d472b2cb" + integrity sha512-y0+tDxcTZ9BHBBKBJbjZxLUXb+zQZCylf7y/jTvDPNx76J0hYYc+F9zHzyqBLeorSKepLTk6yI8hw3NXbAQB3g== + dependencies: + "@walletconnect/environment" "^1.0.1" + "@walletconnect/jsonrpc-types" "^1.0.2" + tslib "1.14.1" + +"@walletconnect/randombytes@^1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@walletconnect/randombytes/-/randombytes-1.0.3.tgz#e795e4918367fd1e6a2215e075e64ab93e23985b" + integrity sha512-35lpzxcHFbTN3ABefC9W+uBpNZl1GC4Wpx0ed30gibfO/y9oLdy1NznbV96HARQKSBV9J9M/rrtIvf6a23jfYw== + dependencies: + "@walletconnect/encoding" "^1.0.2" + "@walletconnect/environment" "^1.0.1" + randombytes "^2.1.0" + tslib "1.14.1" + +"@walletconnect/safe-json@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@walletconnect/safe-json/-/safe-json-1.0.0.tgz#12eeb11d43795199c045fafde97e3c91646683b2" + integrity sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg== + +"@walletconnect/socket-transport@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/socket-transport/-/socket-transport-1.8.0.tgz#9a1128a249628a0be11a0979b522fe82b44afa1b" + integrity sha512-5DyIyWrzHXTcVp0Vd93zJ5XMW61iDM6bcWT4p8DTRfFsOtW46JquruMhxOLeCOieM4D73kcr3U7WtyR4JUsGuQ== + dependencies: + "@walletconnect/types" "^1.8.0" + "@walletconnect/utils" "^1.8.0" + ws "7.5.3" + +"@walletconnect/types@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.8.0.tgz#3f5e85b2d6b149337f727ab8a71b8471d8d9a195" + integrity sha512-Cn+3I0V0vT9ghMuzh1KzZvCkiAxTq+1TR2eSqw5E5AVWfmCtECFkVZBP6uUJZ8YjwLqXheI+rnjqPy7sVM4Fyg== + +"@walletconnect/utils@^1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.8.0.tgz#2591a197c1fa7429941fe428876088fda6632060" + integrity sha512-zExzp8Mj1YiAIBfKNm5u622oNw44WOESzo6hj+Q3apSMIb0Jph9X3GDIdbZmvVZsNPxWDL7uodKgZcCInZv2vA== + dependencies: + "@walletconnect/browser-utils" "^1.8.0" + "@walletconnect/encoding" "^1.0.1" + "@walletconnect/jsonrpc-utils" "^1.0.3" + "@walletconnect/types" "^1.8.0" + bn.js "4.11.8" + js-sha3 "0.8.0" + query-string "6.13.5" + +"@walletconnect/window-getters@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.0.tgz#1053224f77e725dfd611c83931b5f6c98c32bfc8" + integrity sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA== + +"@walletconnect/window-getters@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@walletconnect/window-getters/-/window-getters-1.0.1.tgz#f36d1c72558a7f6b87ecc4451fc8bd44f63cbbdc" + integrity sha512-vHp+HqzGxORPAN8gY03qnbTMnhqIwjeRJNOMOAzePRg4xVEEE2WvYsI9G2NMjOknA8hnuYbU3/hwLcKbjhc8+Q== + dependencies: + tslib "1.14.1" + +"@walletconnect/window-metadata@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@walletconnect/window-metadata/-/window-metadata-1.0.0.tgz#93b1cc685e6b9b202f29c26be550fde97800c4e5" + integrity sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA== + dependencies: + "@walletconnect/window-getters" "^1.0.0" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -3173,6 +3351,11 @@ adjust-sourcemap-loader@^4.0.0: loader-utils "^2.0.0" regex-parser "^2.2.11" +aes-js@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" + integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== + agent-base@6: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -3714,6 +3897,11 @@ bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== +bn.js@4.11.8: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: version "4.12.0" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" @@ -3760,6 +3948,11 @@ bottleneck@^2.15.3: resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91" integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw== +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -4774,6 +4967,11 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-browser@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.2.0.tgz#c9cd5afa96a6a19fda0bbe9e9be48a6b6e1e9c97" + integrity sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA== + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -6089,7 +6287,7 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" -hash.js@^1.0.0, hash.js@^1.0.3: +hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -6672,7 +6870,7 @@ is-typed-array@^1.1.3, is-typed-array@^1.1.9: for-each "^0.3.3" has-tostringtag "^1.0.0" -is-typedarray@^1.0.0: +is-typedarray@1.0.0, is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -7205,7 +7403,7 @@ js-sha256@^0.9.0: resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== -js-sha3@^0.8.0: +js-sha3@0.8.0, js-sha3@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== @@ -7382,6 +7580,11 @@ jws@^3.2.2: jwa "^1.4.1" safe-buffer "^5.0.1" +keyvaluestorage-interface@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff" + integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g== + kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -7571,6 +7774,11 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lottie-web@^5.9.6: + version "5.10.0" + resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.10.0.tgz#72563f22efdcf2b8f7e8359743514930ebaf5f8c" + integrity sha512-q2hfqKrGXNkwjSSZjKxf3fWMi0e3ZBc03qBkVWoGbwUJ7BcG+9YXjMPtmmhitzk8Nc6VQ5PRnh9yInPdfq0PZg== + lower-case@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28" @@ -8982,6 +9190,18 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= +qr-code-styling@^1.6.0-rc.1: + version "1.6.0-rc.1" + resolved "https://registry.yarnpkg.com/qr-code-styling/-/qr-code-styling-1.6.0-rc.1.tgz#6c89e185fa50cc9135101085c12ae95b06f1b290" + integrity sha512-ModRIiW6oUnsP18QzrRYZSc/CFKFKIdj7pUs57AEVH20ajlglRpN3HukjHk0UbNMTlKGuaYl7Gt6/O5Gg2NU2Q== + dependencies: + qrcode-generator "^1.4.3" + +qrcode-generator@^1.4.3: + version "1.4.4" + resolved "https://registry.yarnpkg.com/qrcode-generator/-/qrcode-generator-1.4.4.tgz#63f771224854759329a99048806a53ed278740e7" + integrity sha512-HM7yY8O2ilqhmULxGMpcHSF1EhJJ9yBj8gvDEuZ6M+KGJ0YY2hKpnXvRD+hZPLrDVck3ExIGhmPtSdcjC+guuw== + qs@6.9.7: version "6.9.7" resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe" @@ -8994,6 +9214,15 @@ qs@^6.10.2: dependencies: side-channel "^1.0.4" +query-string@6.13.5: + version "6.13.5" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-6.13.5.tgz#99e95e2fb7021db90a6f373f990c0c814b3812d8" + integrity sha512-svk3xg9qHR39P3JlHuD7g3nRnyay5mHbrPctEBDUxUkHRifPHXJDhBUycdCC0NBjXoDf44Gb+IsOZL1Uwn8M/Q== + dependencies: + decode-uri-component "^0.2.0" + split-on-first "^1.0.0" + strict-uri-encode "^2.0.0" + querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -10040,6 +10269,11 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" +split-on-first@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/split-on-first/-/split-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f" + integrity sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -10074,6 +10308,11 @@ stream@^0.0.2: dependencies: emitter-component "^1.1.1" +strict-uri-encode@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" + integrity sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ== + string-length@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" @@ -10594,7 +10833,7 @@ tsconfig-paths@^3.14.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1: +tslib@1.14.1, tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -10663,7 +10902,7 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typedarray-to-buffer@^3.1.5: +typedarray-to-buffer@3.1.5, typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== @@ -11370,6 +11609,11 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +ws@7.5.3: + version "7.5.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.3.tgz#160835b63c7d97bfab418fc1b8a9fced2ac01a74" + integrity sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg== + ws@^7.4.6: version "7.5.7" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" From 5c7534801773cac2d526d623596eebc50abb6d79 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 6 Dec 2022 20:11:41 +0530 Subject: [PATCH 64/86] remove redux dependency in inner component --- .../Modules/ABI/ABINetworks/ABINetworks.tsx | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/components/Modules/ABI/ABINetworks/ABINetworks.tsx b/src/components/Modules/ABI/ABINetworks/ABINetworks.tsx index bed59c64..a294a914 100644 --- a/src/components/Modules/ABI/ABINetworks/ABINetworks.tsx +++ b/src/components/Modules/ABI/ABINetworks/ABINetworks.tsx @@ -1,12 +1,9 @@ import './ABINetworks.scss'; import React, {} from "react"; import PodcastsIcon from "@mui/icons-material/Podcasts"; -import {Box, Chip, Grid} from "@mui/material"; +import {Box, Grid} from "@mui/material"; import {shadedClr2} from "../../../../utils/common"; -import {useSelector} from "react-redux"; -import {RootState} from "../../../../redux/store"; import {ABIContractNetworks} from "algosdk"; -import {CoreNode} from "../../../../packages/core-sdk/classes/core/CoreNode"; import {theme} from "../../../../theme"; @@ -19,10 +16,6 @@ function ABINetworks(props): JSX.Element { const hasNetworks = Object.keys(networks).length > 0; - const node = useSelector((state: RootState) => state.node); - const {status, versionsCheck, genesis, health} = node; - const coreNodeInstance = new CoreNode(status, versionsCheck, genesis, health); - return (
@@ -59,12 +52,7 @@ function ABINetworks(props): JSX.Element {
- {coreNodeInstance.getGenesisHash() === name ?
- {networks[name].appID} - { - window.open("/explorer/application/" + networks[name].appID , "_blank"); - }}> -
: networks[name].appID} + {networks[name].appID}
From 252d58ae6bb7a64509d64f9b46067c2b5b1da6ba Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Tue, 6 Dec 2022 20:48:14 +0530 Subject: [PATCH 65/86] remove wallet dependency in abi studio inner components --- src/components/LeftBar/LeftBar.tsx | 6 ++-- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 15 ++++----- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 14 ++++----- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 31 ++++++++----------- .../Modules/ABI/ABIMethods/ABIMethods.tsx | 8 +++-- .../Modules/ABI/ABIStudio/ABIStudio.tsx | 6 +++- .../AppManager/CreateApp/CreateApp.tsx | 2 +- src/redux/wallet/actions/wallet.ts | 8 ++--- 8 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index 792482fe..d0d7183a 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -138,12 +138,12 @@ function LeftBar(): JSX.Element {
- {wallet.information.address ?
+ {wallet.account.address ?
- {wallet.information.address} + {wallet.account.address}
{ - navigate('/explorer/account/' + wallet.information.address); + navigate('/explorer/account/' + wallet.account.address); closeWalletMenu(); e.preventDefault(); e.stopPropagation(); diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 004a4553..4efd12b2 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -9,15 +9,17 @@ import {ABIContract, ABIContractParams} from "algosdk"; import ABIConfig from "../ABIConfig/ABIConfig"; import CreateApp from "../../AppManager/CreateApp/CreateApp"; import {showSnack} from "../../../../redux/common/actions/snackbar"; -import {useDispatch, useSelector} from "react-redux"; -import {RootState} from "../../../../redux/store"; +import {useDispatch} from "react-redux"; +import {A_AccountInformation} from "../../../../packages/core-sdk/types"; +import wallet, {defaultAccount} from "../../../../redux/wallet/actions/wallet"; type ABIEditorProps = { abi: ABIContractParams, hideNetworks?: boolean, supportExecutor?: boolean, supportCreateApp?: boolean, - supportConfig?: boolean + supportConfig?: boolean, + account?: A_AccountInformation }; interface ABIEditorState{ @@ -30,11 +32,10 @@ const initialState: ABIEditorState = { showCreateApp: false }; -function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false, supportCreateApp = false, supportConfig = false}: ABIEditorProps): JSX.Element { +function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false, supportCreateApp = false, supportConfig = false, account = defaultAccount}: ABIEditorProps): JSX.Element { const abiInstance = new ABIContract(abi); const networks = abiInstance.networks; - const wallet = useSelector((state: RootState) => state.wallet); const dispatch = useDispatch(); const [ @@ -77,7 +78,7 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support variant={"outlined"} size={"small"} onClick={() => { - if (!wallet.information.address) { + if (!account.address) { dispatch(showSnack({ severity: 'error', message: 'Please connect your wallet' @@ -99,7 +100,7 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support
{!hideNetworks ? : ''} - +
diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 465732e8..4a19205e 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -14,13 +14,14 @@ import ABIMethodExecutor from "../ABIMethodExecutor/ABIMethodExecutor"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {Alert} from "@mui/lab"; import {showSnack} from "../../../../redux/common/actions/snackbar"; -import {useDispatch, useSelector} from "react-redux"; -import {RootState} from "../../../../redux/store"; +import {useDispatch} from "react-redux"; import {ABI_METHOD_EXECUTOR_SUPPORTED_TXN_TYPES} from "../../../../packages/abi/types"; +import {A_AccountInformation} from "../../../../packages/core-sdk/types"; type ABIMethodProps = { method: ABIMethodParams, - supportExecutor?: boolean + supportExecutor?: boolean, + account: A_AccountInformation }; interface ABIMethodState{ @@ -31,10 +32,9 @@ const initialState: ABIMethodState = { showExecutor: false }; -function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Element { +function ABIMethod({method, supportExecutor = true, account}: ABIMethodProps): JSX.Element { const dispatch = useDispatch(); - const wallet = useSelector((state: RootState) => state.wallet); const abiMethodInstance = new ABIMethodSDK(method); const args = abiMethodInstance.args; @@ -61,7 +61,7 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen ev.preventDefault(); ev.stopPropagation(); - if (!wallet.information.address) { + if (!account.address) { dispatch(showSnack({ severity: 'error', message: 'Please connect your wallet' @@ -158,7 +158,7 @@ function ABIMethod({method, supportExecutor = true}: ABIMethodProps): JSX.Elemen
{ setState(prevState => ({...prevState, showExecutor: false})); - }}> + }} account={account}>
); } diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 4398389d..647a3ced 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -35,7 +35,7 @@ import {isNumber} from "../../../../utils/common"; import {getOnCompleteOperations} from "../../../../packages/core-sdk/classes/core/CoreApplication"; import AlgoIcon from "../../Explorer/AlgoIcon/AlgoIcon"; import AssetPicker from "./AssetPicker/AssetPicker"; -import {A_Asset} from "../../../../packages/core-sdk/types"; +import {A_AccountInformation, A_Asset} from "../../../../packages/core-sdk/types"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -51,22 +51,10 @@ const ShadedInput = styled(InputBase)(({ theme }) => { interface ABIMethodExecutorProps{ show: boolean, method: ABIMethodParams, - handleClose?: Function + handleClose?: Function, + account: A_AccountInformation } -const defaultProps: ABIMethodExecutorProps = { - show: false, - method: { - args: [], - name: '', - returns: { - type: '', - desc: '', - }, - desc: '' - } -}; - interface ABIMethodExecutorState{ appId: string, executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], @@ -107,9 +95,16 @@ const argTransactionSx = { background: theme.palette.common.white.toString() }; -function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.method, handleClose}: ABIMethodExecutorProps): JSX.Element { +function ABIMethodExecutor({show = false, method = { + args: [], + name: '', + returns: { + type: '', + desc: '', + }, + desc: '' +}, handleClose, account}: ABIMethodExecutorProps): JSX.Element { - const wallet = useSelector((state: RootState) => state.wallet); const dispatch = useDispatch(); const [ {appId, executorArgs, creation, creationParams, error, success}, @@ -213,7 +208,7 @@ function ABIMethodExecutor({show = defaultProps.show, method = defaultProps.meth try { dispatch(showLoader('Signing transaction')); const abiMethodExecutorInstance = new ABIMethodExecutorCls(method); - const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(creation ? undefined : Number(appId) , wallet.information.address, executorArgs, creation, creationParams); + const unsignedTxns = await abiMethodExecutorInstance.getUnsignedTxns(creation ? undefined : Number(appId) , account.address, executorArgs, creation, creationParams); const signedTxns = await dappflow.signer.signGroupTxns(unsignedTxns.map((unsignedTxn) => { return unsignedTxn.txn; diff --git a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx index 8a915416..bc82be8a 100644 --- a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx +++ b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx @@ -6,13 +6,15 @@ import {ABIContract, ABIContractParams} from "algosdk"; import {theme} from "../../../../theme"; import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; import LinkToApplication from "../../Explorer/Common/Links/LinkToApplication"; +import {A_AccountInformation} from "../../../../packages/core-sdk/types"; type ABIMethodsProps = { abi: ABIContractParams, - supportExecutor?: boolean + supportExecutor?: boolean, + account: A_AccountInformation }; -function ABIMethods({abi, supportExecutor = false}: ABIMethodsProps): JSX.Element { +function ABIMethods({abi, supportExecutor = false, account}: ABIMethodsProps): JSX.Element { const abiInstance = new ABIContract(abi); const appId = new ABIConfig().getAppId(); @@ -35,7 +37,7 @@ function ABIMethods({abi, supportExecutor = false}: ABIMethodsProps): JSX.Elemen
{abiInstance.methods.map((method, index) => { return
- +
; })}
diff --git a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx index 99df4e74..882aea81 100644 --- a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx +++ b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx @@ -4,6 +4,8 @@ import ABIEditor from "../ABIEditor/ABIEditor"; import ABIActions from "../ABIActions/ABIActions"; import {ABIContractParams} from "algosdk"; import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; +import {useSelector} from "react-redux"; +import {RootState} from "../../../../redux/store"; interface ABIStudioState{ imported: boolean, @@ -18,6 +20,8 @@ const initialState: ABIStudioState = { function ABIStudio(): JSX.Element { + const wallet = useSelector((state: RootState) => state.wallet); + useEffect(() => { const storedAbi = localStorage.getItem('abi'); if (storedAbi) { @@ -48,7 +52,7 @@ function ABIStudio(): JSX.Element { new ABIConfig().setAppId(""); localStorage.setItem('abi', JSON.stringify(abi)); }}> - {imported ? : ''} + {imported ? : ''}
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index ae88d29a..fbf49138 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -217,7 +217,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n fee: 0, firstRound: 0, flatFee: false, - from: wallet.information.address, + from: wallet.account.address, genesisHash: "", genesisID: "", lastRound: 0, diff --git a/src/redux/wallet/actions/wallet.ts b/src/redux/wallet/actions/wallet.ts index 921c253e..b40b8475 100644 --- a/src/redux/wallet/actions/wallet.ts +++ b/src/redux/wallet/actions/wallet.ts @@ -7,10 +7,10 @@ import dappflow from "../../../utils/dappflow"; interface Wallet { - information: A_AccountInformation + account: A_AccountInformation } -const information: A_AccountInformation = { +export const defaultAccount: A_AccountInformation = { address: "", amount: 0, "min-balance": 0, @@ -31,7 +31,7 @@ const information: A_AccountInformation = { } const initialState: Wallet = { - information + account: defaultAccount } export const loadWallet = createAsyncThunk( @@ -70,7 +70,7 @@ export const walletSlice = createSlice({ }, extraReducers: (builder) => { builder.addCase(loadWallet.fulfilled, (state, action: PayloadAction) => { - state.information = action.payload; + state.account = action.payload; }); } }); From a25b9cce3ee553ce837bd8d20c3b0272ef5d4362 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 7 Dec 2022 01:11:32 +0530 Subject: [PATCH 66/86] use state management for abi studio component --- src/components/LeftBar/Settings/Settings.tsx | 4 +- .../Modules/ABI/ABIConfig/ABIConfig.tsx | 47 +++----- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 24 +--- .../Modules/ABI/ABIMethod/ABIMethod.tsx | 7 +- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 18 ++- .../Modules/ABI/ABIMethods/ABIMethods.tsx | 40 ++++++- .../Modules/ABI/ABIStudio/ABIStudio.tsx | 38 ++----- .../AppManager/CreateApp/CreateApp.tsx | 5 +- src/packages/abi/classes/ABIConfig.ts | 10 -- src/redux/abi/actions/abiStudio.ts | 103 ++++++++++++++++++ src/redux/store.ts | 4 +- 11 files changed, 185 insertions(+), 115 deletions(-) delete mode 100644 src/packages/abi/classes/ABIConfig.ts create mode 100644 src/redux/abi/actions/abiStudio.ts diff --git a/src/components/LeftBar/Settings/Settings.tsx b/src/components/LeftBar/Settings/Settings.tsx index eefe489d..9b464db9 100644 --- a/src/components/LeftBar/Settings/Settings.tsx +++ b/src/components/LeftBar/Settings/Settings.tsx @@ -22,7 +22,7 @@ import {isBrave} from "../../../packages/core-sdk/utils"; import {NodeConnectionParams} from "../../../packages/core-sdk/types"; import CloseIcon from '@mui/icons-material/Close'; import {logOut} from "../../../redux/wallet/actions/wallet"; -import ABIConfig from "../../../packages/abi/classes/ABIConfig"; +import {updateAppId} from "../../../redux/abi/actions/abiStudio"; const nodeConfig = getNodeConfig(); @@ -163,7 +163,7 @@ function Settings(): JSX.Element { dispatch(hideSettings()); dispatch(hideLoader()); dispatch(logOut()); - new ABIConfig().setAppId(""); + dispatch(updateAppId("")); window.location.reload(); } diff --git a/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx index b9c230de..349d83bd 100644 --- a/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx +++ b/src/components/Modules/ABI/ABIConfig/ABIConfig.tsx @@ -1,5 +1,5 @@ import './ABIConfig.scss'; -import React, {Fragment, useEffect, useState} from "react"; +import React, {Fragment, useRef} from "react"; import { Button, Dialog, @@ -18,8 +18,8 @@ import {ApplicationClient} from "../../../../packages/core-sdk/clients/applicati import dappflow from "../../../../utils/dappflow"; import {handleException} from "../../../../redux/common/actions/exception"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; -import ABIConfigCls from '../../../../packages/abi/classes/ABIConfig'; import CloseIcon from "@mui/icons-material/Close"; +import {updateAppId} from "../../../../redux/abi/actions/abiStudio"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -35,37 +35,15 @@ const ShadedInput = styled(InputBase)(({ theme }) => { interface ABIConfigProps{ show: boolean, - handleClose?: Function -} - -const defaultProps: ABIConfigProps = { - show: false -}; - -interface ABIConfigState{ + handleClose?: Function, appId: string } -const initialState: ABIConfigState = { - appId: '' -}; - -function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX.Element { +function ABIConfig({show = false, handleClose, appId = ''}: ABIConfigProps): JSX.Element { const dispatch = useDispatch(); - - const [ - {appId}, - setState - ] = useState({ - ...initialState - }); - - useEffect(() => { - const savedAppId = new ABIConfigCls().getAppId(); - setState(prevState => ({...prevState, appId: savedAppId})); - }, [show]); + const appIdRef = useRef(); function onClose(ev) { handleClose(); @@ -85,7 +63,7 @@ function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX
-
ABI Config
+
@@ -100,12 +78,9 @@ function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX
App ID { - setState(prevState => ({...prevState, appId: ev.target.value})); - } - } + inputRef={appIdRef} fullWidth/> @@ -119,6 +94,10 @@ function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX onClick={async (ev) => { + + // @ts-ignore + const appId = appIdRef.current.value; + if (appId) { if (!isNumber(appId)) { dispatch(showSnack({ @@ -140,7 +119,7 @@ function ABIConfig({show = defaultProps.show, handleClose}: ABIConfigProps): JSX } - new ABIConfigCls().setAppId(appId || ""); + dispatch(updateAppId(appId)) dispatch(showSnack({ severity: 'success', diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index 4efd12b2..3bf447f7 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -6,20 +6,19 @@ import {Box, Button, Grid} from "@mui/material"; import ABIMethods from "../ABIMethods/ABIMethods"; import ABINetworks from "../ABINetworks/ABINetworks"; import {ABIContract, ABIContractParams} from "algosdk"; -import ABIConfig from "../ABIConfig/ABIConfig"; import CreateApp from "../../AppManager/CreateApp/CreateApp"; import {showSnack} from "../../../../redux/common/actions/snackbar"; import {useDispatch} from "react-redux"; import {A_AccountInformation} from "../../../../packages/core-sdk/types"; -import wallet, {defaultAccount} from "../../../../redux/wallet/actions/wallet"; +import {defaultAccount} from "../../../../redux/wallet/actions/wallet"; type ABIEditorProps = { abi: ABIContractParams, hideNetworks?: boolean, supportExecutor?: boolean, supportCreateApp?: boolean, - supportConfig?: boolean, - account?: A_AccountInformation + account?: A_AccountInformation, + appId?: string }; interface ABIEditorState{ @@ -32,14 +31,14 @@ const initialState: ABIEditorState = { showCreateApp: false }; -function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false, supportCreateApp = false, supportConfig = false, account = defaultAccount}: ABIEditorProps): JSX.Element { +function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, supportExecutor = false, supportCreateApp = false, appId = '', account = defaultAccount}: ABIEditorProps): JSX.Element { const abiInstance = new ABIContract(abi); const networks = abiInstance.networks; const dispatch = useDispatch(); const [ - {showConfig, showCreateApp}, + {showCreateApp}, setState ] = useState(initialState); @@ -62,17 +61,6 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support
- {supportConfig ?
- - {setState(prevState => ({...prevState, showConfig: false}));}}> -
: ''} - {supportCreateApp ?
diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 4a19205e..7e62c89b 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -21,7 +21,8 @@ import {A_AccountInformation} from "../../../../packages/core-sdk/types"; type ABIMethodProps = { method: ABIMethodParams, supportExecutor?: boolean, - account: A_AccountInformation + account: A_AccountInformation, + appId: string }; interface ABIMethodState{ @@ -32,7 +33,7 @@ const initialState: ABIMethodState = { showExecutor: false }; -function ABIMethod({method, supportExecutor = true, account}: ABIMethodProps): JSX.Element { +function ABIMethod({method, supportExecutor = true, account, appId = ''}: ABIMethodProps): JSX.Element { const dispatch = useDispatch(); const abiMethodInstance = new ABIMethodSDK(method); @@ -156,7 +157,7 @@ function ABIMethod({method, supportExecutor = true, account}: ABIMethodProps): J
- { + { setState(prevState => ({...prevState, showExecutor: false})); }} account={account}>
diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 647a3ced..bf442c9e 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -15,13 +15,11 @@ import { } from "@mui/material"; import OfflineBoltIcon from '@mui/icons-material/OfflineBolt'; import {theme} from "../../../../theme"; -import {useDispatch, useSelector} from "react-redux"; -import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; +import {useDispatch} from "react-redux"; import {handleException} from "../../../../redux/common/actions/exception"; import ABIMethodExecutorCls from "../../../../packages/abi/classes/ABIMethodExecutor"; import {A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, A_ABI_METHOD_EXECUTOR_ARG} from "../../../../packages/abi/types"; import CloseIcon from "@mui/icons-material/Close"; -import {RootState} from "../../../../redux/store"; import dappflow from "../../../../utils/dappflow"; import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; import {TransactionClient} from "../../../../packages/core-sdk/clients/transactionClient"; @@ -36,6 +34,7 @@ import {getOnCompleteOperations} from "../../../../packages/core-sdk/classes/cor import AlgoIcon from "../../Explorer/AlgoIcon/AlgoIcon"; import AssetPicker from "./AssetPicker/AssetPicker"; import {A_AccountInformation, A_Asset} from "../../../../packages/core-sdk/types"; +import {updateAppId} from "../../../../redux/abi/actions/abiStudio"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -52,11 +51,11 @@ interface ABIMethodExecutorProps{ show: boolean, method: ABIMethodParams, handleClose?: Function, - account: A_AccountInformation + account: A_AccountInformation, + appId: string } interface ABIMethodExecutorState{ - appId: string, executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], creation: boolean, creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, @@ -65,7 +64,6 @@ interface ABIMethodExecutorState{ } const initialState: ABIMethodExecutorState = { - appId: '', executorArgs: [], creation: false, creationParams: { @@ -103,11 +101,11 @@ function ABIMethodExecutor({show = false, method = { desc: '', }, desc: '' -}, handleClose, account}: ABIMethodExecutorProps): JSX.Element { +}, handleClose, account, appId = ''}: ABIMethodExecutorProps): JSX.Element { const dispatch = useDispatch(); const [ - {appId, executorArgs, creation, creationParams, error, success}, + {executorArgs, creation, creationParams, error, success}, setState ] = useState({ ...initialState @@ -135,7 +133,7 @@ function ABIMethodExecutor({show = false, method = { value: '' }); }); - setState(prevState => ({...prevState, executorArgs: processedArgs, appId: new ABIConfig().getAppId()})); + setState(prevState => ({...prevState, executorArgs: processedArgs})); }, [show]); @@ -227,7 +225,7 @@ function ABIMethodExecutor({show = false, method = { if (creation) { const txnInstance = new CoreTransaction(txn); - new ABIConfig().setAppId(txnInstance.getAppId().toString()); + dispatch(updateAppId(txnInstance.getAppId().toString())); } setSuccess('Method executed successfully : ' + txId); diff --git a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx index bc82be8a..dcf81df7 100644 --- a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx +++ b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx @@ -1,23 +1,38 @@ import './ABIMethods.scss'; -import React, {} from "react"; +import React, {useState} from "react"; import IntegrationInstructionsOutlinedIcon from "@mui/icons-material/IntegrationInstructionsOutlined"; import ABIMethod from "../ABIMethod/ABIMethod"; import {ABIContract, ABIContractParams} from "algosdk"; import {theme} from "../../../../theme"; -import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; import LinkToApplication from "../../Explorer/Common/Links/LinkToApplication"; import {A_AccountInformation} from "../../../../packages/core-sdk/types"; +import ABIConfig from "../ABIConfig/ABIConfig"; +import {Edit} from "@mui/icons-material"; type ABIMethodsProps = { abi: ABIContractParams, supportExecutor?: boolean, - account: A_AccountInformation + account: A_AccountInformation, + appId: string }; -function ABIMethods({abi, supportExecutor = false, account}: ABIMethodsProps): JSX.Element { +interface ABIMethodsState{ + showConfig: boolean, +} + +const initialState: ABIMethodsState = { + showConfig: false, +}; + +function ABIMethods({abi, supportExecutor = false, account, appId = ''}: ABIMethodsProps): JSX.Element { const abiInstance = new ABIContract(abi); - const appId = new ABIConfig().getAppId(); + + + const [ + {showConfig}, + setState + ] = useState(initialState); return (
@@ -31,13 +46,26 @@ function ABIMethods({abi, supportExecutor = false, account}: ABIMethodsProps): J
App ID : {appId ? : 'null'} + + + { + setState(prevState => ({...prevState, showConfig: true})); + }}> + {setState(prevState => ({...prevState, showConfig: false}));}}> +
{abiInstance.methods.map((method, index) => { return
- +
; })}
diff --git a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx index 882aea81..1939afb2 100644 --- a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx +++ b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx @@ -1,45 +1,27 @@ import './ABIStudio.scss'; -import React, {useEffect, useState} from "react"; +import React, {useEffect} from "react"; import ABIEditor from "../ABIEditor/ABIEditor"; import ABIActions from "../ABIActions/ABIActions"; -import {ABIContractParams} from "algosdk"; -import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; -import {useSelector} from "react-redux"; +import {useDispatch, useSelector} from "react-redux"; import {RootState} from "../../../../redux/store"; +import {loadAbi, updateAbi} from "../../../../redux/abi/actions/abiStudio"; -interface ABIStudioState{ - imported: boolean, - abi: ABIContractParams -} - -const initialState: ABIStudioState = { - imported: false, - abi: {methods: [], name: ""} -}; function ABIStudio(): JSX.Element { + const dispatch = useDispatch(); const wallet = useSelector((state: RootState) => state.wallet); + const abiStudio = useSelector((state: RootState) => state.abiStudio); + const {abi, appId} = abiStudio; useEffect(() => { - const storedAbi = localStorage.getItem('abi'); - if (storedAbi) { - setState(prevState => ({...prevState, abi: JSON.parse(storedAbi), imported: true})); - } - + dispatch(loadAbi()); }, []); - const [ - {imported, abi}, - setState - ] = useState(initialState); - return (
- -
ABI Studio @@ -48,11 +30,9 @@ function ABIStudio(): JSX.Element {
{ - setState(prevState => ({...prevState, abi, imported: true})); - new ABIConfig().setAppId(""); - localStorage.setItem('abi', JSON.stringify(abi)); + dispatch(updateAbi(abi)); }}> - {imported ? : ''} + {abi ? : ''}
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index fbf49138..00f15edb 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -27,9 +27,9 @@ import {isNumber} from "../../../../utils/common"; import {ApplicationTransaction} from "../../../../packages/core-sdk/transactions/applicationTransaction"; import {RootState} from "../../../../redux/store"; import {TransactionClient} from "../../../../packages/core-sdk/clients/transactionClient"; -import ABIConfig from "../../../../packages/abi/classes/ABIConfig"; import {CoreTransaction} from "../../../../packages/core-sdk/classes/core/CoreTransaction"; import {getOnCompleteOperations} from "../../../../packages/core-sdk/classes/core/CoreApplication"; +import {updateAppId} from "../../../../redux/abi/actions/abiStudio"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -242,7 +242,8 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n dispatch(hideLoader()); const txnInstance = new CoreTransaction(txn); - new ABIConfig().setAppId(txnInstance.getAppId().toString()); + dispatch(updateAppId(txnInstance.getAppId().toString())); + handleClose(); dispatch(showSnack({ severity: 'success', diff --git a/src/packages/abi/classes/ABIConfig.ts b/src/packages/abi/classes/ABIConfig.ts deleted file mode 100644 index b598640c..00000000 --- a/src/packages/abi/classes/ABIConfig.ts +++ /dev/null @@ -1,10 +0,0 @@ -export default class ABIConfig { - - setAppId(id: string) { - localStorage.setItem('abi_app_id', id); - } - - getAppId(): string { - return localStorage.getItem('abi_app_id'); - } -} \ No newline at end of file diff --git a/src/redux/abi/actions/abiStudio.ts b/src/redux/abi/actions/abiStudio.ts new file mode 100644 index 00000000..203acc4d --- /dev/null +++ b/src/redux/abi/actions/abiStudio.ts @@ -0,0 +1,103 @@ +import {createAsyncThunk, createSlice, PayloadAction} from '@reduxjs/toolkit' +import {hideLoader, showLoader} from "../../common/actions/loader"; +import {handleException} from "../../common/actions/exception"; +import {ABIContractParams} from "algosdk"; + + +interface AbiStudio { + abi: ABIContractParams, + appId: string +} + +const initialState: AbiStudio = { + abi: { + name: '', + methods: [] + }, + appId: '' +} + +export const loadAbi = createAsyncThunk( + 'abiStudio/loadAbi', + async (_, thunkAPI) => { + const {dispatch} = thunkAPI; + try { + dispatch(showLoader("Loading ABI ...")); + + const storedAbi = localStorage.getItem('abi'); + if (storedAbi) { + dispatch(setAbi(JSON.parse(storedAbi))); + } + + + dispatch(loadAppId()); + dispatch(hideLoader()); + } + catch (e: any) { + dispatch(handleException(e)); + dispatch(hideLoader()); + } + } +); + + +export const loadAppId = createAsyncThunk( + 'abiStudio/loadAppId', + async (_, thunkAPI) => { + const {dispatch} = thunkAPI; + const appId = localStorage.getItem('abi_app_id'); + if (appId) { + dispatch(setAppId(appId)); + } + } +); + +export const updateAbi = createAsyncThunk( + 'abiStudio/updateAbi', + async (abi: ABIContractParams, thunkAPI) => { + const {dispatch} = thunkAPI; + try { + if (abi) { + dispatch(showLoader("Updating ABI ...")); + + localStorage.setItem('abi', JSON.stringify(abi)); + dispatch(setAbi(abi)); + + dispatch(updateAppId('')); + dispatch(hideLoader()); + } + } + catch (e: any) { + dispatch(handleException(e)); + dispatch(hideLoader()); + } + } +); + +export const updateAppId = createAsyncThunk( + 'abiStudio/updateAppId', + async (id: string, thunkAPI) => { + const {dispatch} = thunkAPI; + id = id || ''; + localStorage.setItem('abi_app_id', id); + dispatch(setAppId(id)); + } +); + + + +export const abiStudioSlice = createSlice({ + name: 'abiStudio', + initialState, + reducers: { + setAppId: (state, action: PayloadAction ) => { + state.appId = action.payload; + }, + setAbi: (state, action: PayloadAction ) => { + state.abi = action.payload; + } + } +}); + +export const {setAppId, setAbi} = abiStudioSlice.actions +export default abiStudioSlice.reducer \ No newline at end of file diff --git a/src/redux/store.ts b/src/redux/store.ts index a8d572e9..128e897b 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -22,6 +22,7 @@ import kmd from "./explorer/actions/kmd"; import connectWallet from "./wallet/actions/connectWallet"; import wallet from "./wallet/actions/wallet"; import signer from "./wallet/actions/signer"; +import abiStudio from "./abi/actions/abiStudio"; export const store = configureStore({ reducer: { @@ -47,7 +48,8 @@ export const store = configureStore({ kmd: kmd, connectWallet: connectWallet, wallet: wallet, - signer: signer + signer: signer, + abiStudio: abiStudio }, }); From 4ed15ec1db0314d66fbdadef3360d5cfe9104c7e Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 7 Dec 2022 01:26:50 +0530 Subject: [PATCH 67/86] bugfix --- .../Modules/ABI/ABIMethods/ABIMethods.tsx | 13 +++++++------ .../Sections/ApplicationABI/ApplicationAbi.tsx | 3 ++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx index dcf81df7..629ac287 100644 --- a/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx +++ b/src/components/Modules/ABI/ABIMethods/ABIMethods.tsx @@ -47,18 +47,19 @@ function ABIMethods({abi, supportExecutor = false, account, appId = ''}: ABIMeth App ID : {appId ? : 'null'} - + {supportExecutor ? { - setState(prevState => ({...prevState, showConfig: true})); - }}> + setState(prevState => ({...prevState, showConfig: true})); + }}> {setState(prevState => ({...prevState, showConfig: false}));}}> - + : ''} +
diff --git a/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx b/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx index 9693744b..782e4a6a 100644 --- a/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx +++ b/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx @@ -37,6 +37,7 @@ function ApplicationAbi(props): JSX.Element { const node = useSelector((state: RootState) => state.node); const {status, versionsCheck, genesis, health} = node; const coreNodeInstance = new CoreNode(status, versionsCheck, genesis, health); + const appInstance = new CoreApplication(application.information); return (
@@ -87,7 +88,7 @@ function ApplicationAbi(props): JSX.Element { {application.abiDetails.loaded && application.abiDetails.present ?
- +
: ''} {application.abiDetails.loaded && !application.abiDetails.present ? From d59400288e57c70d18e23b2b614c4ef49ecf8fff Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 7 Dec 2022 01:41:24 +0530 Subject: [PATCH 68/86] remove update abi from app page --- .../Sections/ApplicationABI/ApplicationAbi.tsx | 10 +--------- src/packages/abi/classes/ApplicationABI.ts | 10 ++++++++++ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx b/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx index 782e4a6a..e5b2045b 100644 --- a/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx +++ b/src/components/Modules/Explorer/Records/Application/Sections/ApplicationABI/ApplicationAbi.tsx @@ -58,15 +58,6 @@ function ApplicationAbi(props): JSX.Element { style={{marginLeft: '10px'}} >Attach ABI : ''} - {application.abiDetails.loaded && application.abiDetails.present ? : ''} - {application.abiDetails.loaded && application.abiDetails.present ? - {setState(prevState => ({...prevState, showCreateApp: false}));}}>
: ''} -
+ + + + + {abi.methods.map((method) => { + return { + setState(prevState => ({...prevState, method: method, showCreateApp: true})); + closeCreateAppMenu(); + e.preventDefault(); + e.stopPropagation(); + } + }> + {method.name} + ; + })} + + + + { + setState(prevState => ({...prevState, method: defaultMethod, showCreateApp: false})); + }} account={account}> + diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index bf442c9e..07c9a83f 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -6,7 +6,7 @@ import { } from "algosdk"; import { Alert, - Button, ButtonGroup, + Button, Dialog, DialogActions, DialogContent, @@ -52,12 +52,12 @@ interface ABIMethodExecutorProps{ method: ABIMethodParams, handleClose?: Function, account: A_AccountInformation, - appId: string + appId: string, + creation?: boolean } interface ABIMethodExecutorState{ executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], - creation: boolean, creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, error: string, success: string @@ -65,7 +65,6 @@ interface ABIMethodExecutorState{ const initialState: ABIMethodExecutorState = { executorArgs: [], - creation: false, creationParams: { id: '', approvalProgram: '', @@ -93,11 +92,11 @@ const argTransactionSx = { background: theme.palette.common.white.toString() }; -function ABIMethodExecutor({show = false, method = { +function ABIMethodExecutor({show = false, creation = false, method = { args: [], name: '', returns: { - type: '', + type: 'void', desc: '', }, desc: '' @@ -105,7 +104,7 @@ function ABIMethodExecutor({show = false, method = { const dispatch = useDispatch(); const [ - {executorArgs, creation, creationParams, error, success}, + {executorArgs, creationParams, error, success}, setState ] = useState({ ...initialState @@ -213,21 +212,22 @@ function ABIMethodExecutor({show = false, method = { })); dispatch(hideLoader()); - const txnInstance = new BaseTransaction(dappflow.network); dispatch(showLoader('Broadcasting transaction to network')); + const txnInstance = new BaseTransaction(dappflow.network); const {txId} = await txnInstance.send(signedTxns); dispatch(hideLoader()); dispatch(showLoader('Waiting for confirmation')); await txnInstance.waitForConfirmation(txId); const txn = await new TransactionClient(dappflow.network).get(txId); - dispatch(hideLoader()); + if (creation) { const txnInstance = new CoreTransaction(txn); dispatch(updateAppId(txnInstance.getAppId().toString())); } - + + dispatch(hideLoader()); setSuccess('Method executed successfully : ' + txId); } catch (e: any) { @@ -306,14 +306,14 @@ function ABIMethodExecutor({show = false, method = {
-
- Do you want to use this method for app creation ? -
- - - - - + {/*
*/} + {/* Do you want to use this method for app creation ?*/} + {/*
*/} + + {/**/} + {/* */} + {/* */} + {/**/} {creation ?
From e9fcdac44a8e0cc0479194ef21286e3a23a51fa6 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 7 Dec 2022 13:12:36 +0530 Subject: [PATCH 70/86] view transaction agter abi txn is success --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 37 ++++++++++++++++--- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 07c9a83f..32eb4438 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -60,7 +60,8 @@ interface ABIMethodExecutorState{ executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, error: string, - success: string + success: string, + txId: string } const initialState: ABIMethodExecutorState = { @@ -78,7 +79,8 @@ const initialState: ABIMethodExecutorState = { onComplete: OnApplicationComplete.NoOpOC.toString() }, error: '', - success: '' + success: '', + txId: '' }; const formLabelSx = { @@ -104,7 +106,7 @@ function ABIMethodExecutor({show = false, creation = false, method = { const dispatch = useDispatch(); const [ - {executorArgs, creationParams, error, success}, + {executorArgs, creationParams, error, success, txId}, setState ] = useState({ ...initialState @@ -147,6 +149,7 @@ function ABIMethodExecutor({show = false, creation = false, method = { function resetResult() { setError(""); setSuccess(""); + setTxId(""); } function setError(msg: string) { @@ -159,6 +162,10 @@ function ABIMethodExecutor({show = false, creation = false, method = { focusResult(); } + function setTxId(id: string) { + setState(prevState => ({...prevState, txId: id})); + } + function focusResult() { // @ts-ignore resultRef.current.focus(); @@ -226,9 +233,10 @@ function ABIMethodExecutor({show = false, creation = false, method = { const txnInstance = new CoreTransaction(txn); dispatch(updateAppId(txnInstance.getAppId().toString())); } - + dispatch(hideLoader()); - setSuccess('Method executed successfully : ' + txId); + setSuccess('Method executed successfully : '); + setTxId(txId); } catch (e: any) { dispatch(hideLoader()); @@ -757,8 +765,25 @@ function ABIMethodExecutor({show = false, creation = false, method = {
{success}
+ +
+ Transaction ID +
+ {txId} +
+
+ + +
- {/**/}
: ''} From 035a4e1023a0c7bb339bf328542a38282b5430c7 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 7 Dec 2022 20:09:22 +0530 Subject: [PATCH 71/86] parse and display ABI call return value --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 47 +++++++------- .../AppCallTxnArguments.tsx | 11 +++- .../AppCallTxnReturnValue.scss | 29 +++++++++ .../AppCallTxnReturnValue.tsx | 62 +++++++++++++++++++ .../core-sdk/classes/core/CoreTransaction.ts | 11 ++++ 5 files changed, 136 insertions(+), 24 deletions(-) create mode 100644 src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss create mode 100644 src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.tsx diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 32eb4438..5eaa9855 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -33,8 +33,10 @@ import {isNumber} from "../../../../utils/common"; import {getOnCompleteOperations} from "../../../../packages/core-sdk/classes/core/CoreApplication"; import AlgoIcon from "../../Explorer/AlgoIcon/AlgoIcon"; import AssetPicker from "./AssetPicker/AssetPicker"; -import {A_AccountInformation, A_Asset} from "../../../../packages/core-sdk/types"; +import {A_AccountInformation, A_Asset, A_SearchTransaction} from "../../../../packages/core-sdk/types"; import {updateAppId} from "../../../../redux/abi/actions/abiStudio"; +import AppCallTxnReturnValue + from "../../Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue"; const ShadedInput = styled(InputBase)(({ theme }) => { @@ -60,8 +62,7 @@ interface ABIMethodExecutorState{ executorArgs: A_ABI_METHOD_EXECUTOR_ARG[], creationParams: A_ABI_METHOD_EXECUTOR_APP_CREATION_PARAMS, error: string, - success: string, - txId: string + txn?: A_SearchTransaction } const initialState: ABIMethodExecutorState = { @@ -79,8 +80,7 @@ const initialState: ABIMethodExecutorState = { onComplete: OnApplicationComplete.NoOpOC.toString() }, error: '', - success: '', - txId: '' + txn: null }; const formLabelSx = { @@ -106,7 +106,7 @@ function ABIMethodExecutor({show = false, creation = false, method = { const dispatch = useDispatch(); const [ - {executorArgs, creationParams, error, success, txId}, + {executorArgs, creationParams, error, txn}, setState ] = useState({ ...initialState @@ -148,8 +148,7 @@ function ABIMethodExecutor({show = false, creation = false, method = { function resetResult() { setError(""); - setSuccess(""); - setTxId(""); + setTxn(null); } function setError(msg: string) { @@ -157,13 +156,11 @@ function ABIMethodExecutor({show = false, creation = false, method = { focusResult(); } - function setSuccess(msg: string) { - setState(prevState => ({...prevState, success: msg})); - focusResult(); - } - function setTxId(id: string) { - setState(prevState => ({...prevState, txId: id})); + function setTxn(txn1: A_SearchTransaction) { + console.log(txn1); + setState(prevState => ({...prevState, txn: txn1})); + focusResult(); } function focusResult() { @@ -226,17 +223,18 @@ function ABIMethodExecutor({show = false, creation = false, method = { dispatch(showLoader('Waiting for confirmation')); await txnInstance.waitForConfirmation(txId); - const txn = await new TransactionClient(dappflow.network).get(txId); + dispatch(hideLoader()); + dispatch(showLoader('Fetching transaction')); + const txn1 = await new TransactionClient(dappflow.network).get(txId); if (creation) { - const txnInstance = new CoreTransaction(txn); + const txnInstance = new CoreTransaction(txn1); dispatch(updateAppId(txnInstance.getAppId().toString())); } + setTxn(txn1); dispatch(hideLoader()); - setSuccess('Method executed successfully : '); - setTxId(txId); } catch (e: any) { dispatch(hideLoader()); @@ -759,24 +757,24 @@ function ABIMethodExecutor({show = false, creation = false, method = { } color={"warning"} sx={{wordBreak: "break-word"}}>{error}
: ''} - {success ?
+ {Boolean(txn) ?
- {success} + Method executed successfully.
Transaction ID
- {txId} + {new CoreTransaction(txn).getId()}
+
+ +
+ +
: ''}
diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx index 327e1f75..7f7395ee 100644 --- a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnArguments/AppCallTxnArguments.tsx @@ -10,6 +10,7 @@ import {CoreAppCall} from "../../../../../../../../../packages/core-sdk/classes/ import {ABIContractParams} from "algosdk"; import ABIMethodSignature from "../../../../../../../ABI/ABIMethodSignature/ABIMethodSignature"; import {CoreTransaction} from "../../../../../../../../../packages/core-sdk/classes/core/CoreTransaction"; +import AppCallTxnReturnValue from "../AppCallTxnReturnValue/AppCallTxnReturnValue"; interface AppCallTxnArgumentsState{ textEncoding: string, @@ -85,7 +86,7 @@ function AppCallTxnArguments(props): JSX.Element { {method ?
-
+ {abiDecodedArgs.length > 0 ?
Name @@ -98,7 +99,8 @@ function AppCallTxnArguments(props): JSX.Element { -
+
: ''} + {abiDecodedArgs.map((arg, index) => { @@ -120,6 +122,11 @@ function AppCallTxnArguments(props): JSX.Element { })}
+ + +
+ +
:
This transaction did not match with any method signature in the attached ABI diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss new file mode 100644 index 00000000..eb09811e --- /dev/null +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss @@ -0,0 +1,29 @@ +@import "src/assets/colors"; + +.app-call-txn-return-value-wrapper { + .app-call-txn-return-value-container { + .method-signature { + .method-sig-section { + margin-bottom: 10px; + padding-bottom: 10px; + border-bottom: 1px solid $color-light; + &:last-child { + border-bottom: none; + padding-bottom: 0; + } + .method-sig-section-key { + margin-bottom: 5px; + font-size: 14px; + text-decoration: underline; + } + .method-sig-section-value { + font-weight: bold; + font-family: PoppinsLight !important; + * { + font-family: PoppinsLight !important; + } + } + } + } + } +} \ No newline at end of file diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.tsx b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.tsx new file mode 100644 index 00000000..fd34f3b2 --- /dev/null +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.tsx @@ -0,0 +1,62 @@ +import './AppCallTxnReturnValue.scss'; +import React, {} from "react"; +import {ABIMethodParams, ABIType} from "algosdk"; +import {A_SearchTransaction} from "../../../../../../../../../packages/core-sdk/types"; +import {CoreTransaction} from "../../../../../../../../../packages/core-sdk/classes/core/CoreTransaction"; +import {Alert, Typography} from "@mui/material"; + +type AppCallTxnReturnValueProps = { + transaction: A_SearchTransaction, + method: ABIMethodParams +}; + +function AppCallTxnReturnValue({transaction, method}: AppCallTxnReturnValueProps): JSX.Element { + + + const txnInstance = new CoreTransaction(transaction); + let returnType = method.returns.type.toString(); + let decodedVal; + + if (!returnType || returnType === 'void') { + decodedVal = ''; + } + else { + const codec: ABIType = ABIType.from(returnType); + const returnValBase64 = txnInstance.getReturnValue(); + let bufReturnedVal = Buffer.from(returnValBase64, 'base64'); + bufReturnedVal = bufReturnedVal.slice(4, bufReturnedVal.length) + const uintReturnedVal = Uint8Array.from(bufReturnedVal); + decodedVal = codec.decode(uintReturnedVal).toString(); + } + + + + + return (
+
+
+ + Returned +
+
+ Type +
+
+ {returnType} +
+
+
+
+ Value +
+
+ {decodedVal} +
+
+
+
+
+
); +} + +export default AppCallTxnReturnValue; diff --git a/src/packages/core-sdk/classes/core/CoreTransaction.ts b/src/packages/core-sdk/classes/core/CoreTransaction.ts index 0306b9cc..a90bcf2f 100644 --- a/src/packages/core-sdk/classes/core/CoreTransaction.ts +++ b/src/packages/core-sdk/classes/core/CoreTransaction.ts @@ -331,4 +331,15 @@ export class CoreTransaction { return payload["close-amount"]; } } + + getLogs(): string[]{ + return this.txn.logs; + } + + getReturnValue(): string { + const logs = this.getLogs(); + if (logs && logs.length > 0) { + return logs[logs.length - 1]; + } + } } \ No newline at end of file From 845155544583459440e8c546ed3fd10b9ad41e0e Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 7 Dec 2022 21:12:22 +0530 Subject: [PATCH 72/86] block execution if app id is null --- src/components/Modules/ABI/ABIMethod/ABIMethod.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx index 7e62c89b..7b246b64 100644 --- a/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx +++ b/src/components/Modules/ABI/ABIMethod/ABIMethod.tsx @@ -69,6 +69,13 @@ function ABIMethod({method, supportExecutor = true, account, appId = ''}: ABIMet })); return; } + if (!appId) { + dispatch(showSnack({ + severity: 'error', + message: 'App ID is null. If you already have a existing app, Please setup your app id using edit button above. If not create a new application' + })); + return; + } if (!new ABIMethodExecutorCls(method).canExecute()) { dispatch(showSnack({ From 284660ccefad8b6fc8ed0a609c11ed02c231c135 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Wed, 7 Dec 2022 22:04:46 +0530 Subject: [PATCH 73/86] encode abi arguments --- .../ABI/ABIMethodExecutor/ABIMethodExecutor.tsx | 11 +++++------ src/packages/abi/classes/ABIMethodExecutor.ts | 13 ++++++++----- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 5eaa9855..11798d63 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -157,9 +157,8 @@ function ABIMethodExecutor({show = false, creation = false, method = { } - function setTxn(txn1: A_SearchTransaction) { - console.log(txn1); - setState(prevState => ({...prevState, txn: txn1})); + function setTxn(txn: A_SearchTransaction) { + setState(prevState => ({...prevState, txn: txn})); focusResult(); } @@ -226,14 +225,14 @@ function ABIMethodExecutor({show = false, creation = false, method = { dispatch(hideLoader()); dispatch(showLoader('Fetching transaction')); - const txn1 = await new TransactionClient(dappflow.network).get(txId); + const txn = await new TransactionClient(dappflow.network).get(txId); if (creation) { - const txnInstance = new CoreTransaction(txn1); + const txnInstance = new CoreTransaction(txn); dispatch(updateAppId(txnInstance.getAppId().toString())); } - setTxn(txn1); + setTxn(txn); dispatch(hideLoader()); } catch (e: any) { diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index 61fccdcc..a074e879 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -69,17 +69,20 @@ export default class ABIMethodExecutor { const dataType = arg.type.toString(); const val = arg.value; + if (dataType.startsWith("uint")) { + return BigInt(val); + } + if (dataType.startsWith('ufixed')) { + return BigInt(val); + } + switch (dataType) { - case "uint8": - case "uint16": - case "uint32": - case "uint64": case "byte": case "asset": case "application": return BigInt(val); case "bool": - return Boolean(val); + return val === 'true'; case "byte[]": return new Uint8Array(Buffer.from(val, "base64")); case "string[7]": From 1aac1bb3ebb54072c5ce4a08ed607bcb9a2ea17d Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Fri, 9 Dec 2022 21:31:23 +0530 Subject: [PATCH 74/86] parse ABI call arguments --- src/packages/abi/classes/ABIMethodExecutor.ts | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/packages/abi/classes/ABIMethodExecutor.ts b/src/packages/abi/classes/ABIMethodExecutor.ts index a074e879..e12a3b94 100644 --- a/src/packages/abi/classes/ABIMethodExecutor.ts +++ b/src/packages/abi/classes/ABIMethodExecutor.ts @@ -1,8 +1,8 @@ import { - ABIArgumentType, + ABIArgumentType, ABIArrayDynamicType, ABIArrayStaticType, ABIMethod, ABIMethodParams, - ABITransactionType, + ABITransactionType, ABITupleType, abiTypeIsTransaction, algosToMicroalgos, AtomicTransactionComposer, @@ -69,27 +69,23 @@ export default class ABIMethodExecutor { const dataType = arg.type.toString(); const val = arg.value; - if (dataType.startsWith("uint")) { + if (dataType.startsWith("uint") || dataType.startsWith('ufixed') || dataType === 'byte' || dataType === 'asset' || dataType === 'application') { return BigInt(val); } - if (dataType.startsWith('ufixed')) { - return BigInt(val); + if (dataType === 'bool') { + return val === 'true'; } - - switch (dataType) { - case "byte": - case "asset": - case "application": - return BigInt(val); - case "bool": - return val === 'true'; - case "byte[]": + if (arg.type instanceof ABIArrayStaticType || arg.type instanceof ABIArrayDynamicType) { + if (dataType.startsWith("byte")) { return new Uint8Array(Buffer.from(val, "base64")); - case "string[7]": - return val.split(','); - default: - return val; + } + return val.split(','); + } + if (arg.type instanceof ABITupleType) { + return ABITupleType.parseTupleContent(val); } + + return val; } getSequenceOfTxnTypes(): string[] { From 2d90dd6022558eaf37ab8bfdacba0727bc37ddf1 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 10 Dec 2022 17:19:49 +0530 Subject: [PATCH 75/86] dev wallets to sign txns for ABI method executor --- src/components/App/AppRouter.tsx | 2 + src/components/LeftBar/LeftBar.tsx | 4 + .../DevWallets/DevWallets/DevWallets.scss | 44 ++++++++++ .../DevWallets/DevWallets/DevWallets.tsx | 84 +++++++++++++++++++ src/db/datastore.ts | 7 +- src/packages/dev-wallets/classes/DevWallet.ts | 34 ++++++++ src/packages/dev-wallets/types.ts | 5 ++ src/redux/devWallets/actions/devWallets.ts | 68 +++++++++++++++ src/redux/store.ts | 4 +- 9 files changed, 249 insertions(+), 3 deletions(-) create mode 100644 src/components/Modules/DevWallets/DevWallets/DevWallets.scss create mode 100644 src/components/Modules/DevWallets/DevWallets/DevWallets.tsx create mode 100644 src/packages/dev-wallets/classes/DevWallet.ts create mode 100644 src/packages/dev-wallets/types.ts create mode 100644 src/redux/devWallets/actions/devWallets.ts diff --git a/src/components/App/AppRouter.tsx b/src/components/App/AppRouter.tsx index f19c2208..5ecae204 100644 --- a/src/components/App/AppRouter.tsx +++ b/src/components/App/AppRouter.tsx @@ -41,6 +41,7 @@ import ABIStudio from "../Modules/ABI/ABIStudio/ABIStudio"; import Dispenser from "../Modules/Dispenser/Dispenser"; import NodeStatus from "../Modules/NodeStatus/NodeStatus"; import ArcHome from "../Modules/ArcPortal/Home/ArcHome"; +import DevWallets from "../Modules/DevWallets/DevWallets/DevWallets"; function AppRouter(): JSX.Element { @@ -105,6 +106,7 @@ function AppRouter(): JSX.Element { }> }> }> + }> }/>
diff --git a/src/components/LeftBar/LeftBar.tsx b/src/components/LeftBar/LeftBar.tsx index d0d7183a..acb7f1d2 100644 --- a/src/components/LeftBar/LeftBar.tsx +++ b/src/components/LeftBar/LeftBar.tsx @@ -26,6 +26,7 @@ import LogoutIcon from '@mui/icons-material/Logout'; import SwapCallsIcon from '@mui/icons-material/SwapCalls'; import AccountBalanceWalletIcon from '@mui/icons-material/AccountBalanceWallet'; import VisibilityIcon from '@mui/icons-material/Visibility'; +import CreditCardIcon from '@mui/icons-material/CreditCard'; function LeftBar(): JSX.Element { @@ -99,6 +100,9 @@ function LeftBar(): JSX.Element { } iconPosition="start" label="Node Status" value="node-status" onClick={() => { navigate('/node-status'); }}/> + } iconPosition="start" label="Dev Wallets" value="dev-wallets" onClick={() => { + navigate('/dev-wallets'); + }}/> diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.scss b/src/components/Modules/DevWallets/DevWallets/DevWallets.scss new file mode 100644 index 00000000..9d6ff6fe --- /dev/null +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.scss @@ -0,0 +1,44 @@ +@import "src/assets/colors"; + +.dev-wallets-wrapper { + .dev-wallets-container { + .dev-wallets-header { + margin-bottom: 15px; + padding-bottom: 20px; + font-size: 20px; + font-weight: bold; + border-bottom: 1px solid $color-grey-light; + } + .dev-wallets-body { + .dev-wallets-actions-wrapper { + .dev-wallets-actions-container { + margin-bottom: 20px; + } + } + + .dev-wallets-list-wrapper { + .dev-wallets-list-container { + border-radius: 10px; + padding: 15px 0; + .wallet-wrapper { + .wallet-container { + background: $color-light; + border-radius: 10px; + margin: 20px; + padding: 20px; + display: flex; + justify-content: space-between; + .wallet-address { + font-size: 13px; + font-weight: bold; + } + .wallet-actions { + + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx new file mode 100644 index 00000000..4b082315 --- /dev/null +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx @@ -0,0 +1,84 @@ +import './DevWallets.scss'; +import React, {useEffect} from "react"; +import {useDispatch, useSelector} from "react-redux"; +import AddIcon from "@mui/icons-material/Add"; +import {Button} from "@mui/material"; +import {shadedClr} from "../../../../utils/common"; +import {createDevWallet, deleteDevWallet, loadDevWallets} from "../../../../redux/devWallets/actions/devWallets"; +import {generateAccount, secretKeyToMnemonic} from 'algosdk' +import {A_Dev_Wallet} from "../../../../packages/dev-wallets/types"; +import {RootState} from "../../../../redux/store"; + + +function DevWallets(): JSX.Element { + + + const dispatch = useDispatch(); + const devWallets = useSelector((state: RootState) => state.devWallets); + const {wallets} = devWallets; + + + useEffect(() => { + dispatch(loadDevWallets()); + }, []); + + return (
+
+ +
+
+ Dev Wallets +
+
+ +
+
+
+ +
+
+ +
+
+ {wallets.map((wallet) => { + return
+
+
+ {wallet.address} +
+
+ +
+
+
; + })} + +
+
+
+
+
); +} + +export default DevWallets; diff --git a/src/db/datastore.ts b/src/db/datastore.ts index e0a34b66..6c1c8bf5 100644 --- a/src/db/datastore.ts +++ b/src/db/datastore.ts @@ -1,13 +1,16 @@ import Dexie, { Table } from 'dexie'; import {A_Application_ABI} from "../packages/abi/types"; +import {A_Dev_Wallet} from "../packages/dev-wallets/types"; export class DappflowDataStore extends Dexie { applicationABIs!: Table; + devWallets!: Table; constructor() { super('dappflow'); - this.version(1).stores({ - applicationABIs: '++id, network, app, abi' + this.version(2).stores({ + applicationABIs: '++id, network, app, abi', + devWallets: '++id, address, mnemonic' }); } } diff --git a/src/packages/dev-wallets/classes/DevWallet.ts b/src/packages/dev-wallets/classes/DevWallet.ts new file mode 100644 index 00000000..6778b2b9 --- /dev/null +++ b/src/packages/dev-wallets/classes/DevWallet.ts @@ -0,0 +1,34 @@ +import {A_Dev_Wallet} from "../types"; +import {dataStore} from "../../../db/datastore"; + +export class DevWallet { + + async save(wallet: A_Dev_Wallet): Promise { + await dataStore.devWallets.add({ + ...wallet + }); + + return this.get(wallet.address); + } + + async get(address: string): Promise { + const wallet = await dataStore.devWallets.get({ + address: address + }); + + return wallet; + } + + async delete(address: string): Promise { + await dataStore.devWallets.where({ + address: address + }).delete(); + + return true + } + + async getAll(): Promise { + const wallets = await dataStore.devWallets.toArray() + return wallets; + } +} \ No newline at end of file diff --git a/src/packages/dev-wallets/types.ts b/src/packages/dev-wallets/types.ts new file mode 100644 index 00000000..acab1036 --- /dev/null +++ b/src/packages/dev-wallets/types.ts @@ -0,0 +1,5 @@ +export interface A_Dev_Wallet { + id?: number, + address: string, + mnemonic: string +} diff --git a/src/redux/devWallets/actions/devWallets.ts b/src/redux/devWallets/actions/devWallets.ts new file mode 100644 index 00000000..7c8f4d01 --- /dev/null +++ b/src/redux/devWallets/actions/devWallets.ts @@ -0,0 +1,68 @@ +import {createAsyncThunk, createSlice, PayloadAction} from '@reduxjs/toolkit' +import {A_Dev_Wallet} from "../../../packages/dev-wallets/types"; +import {DevWallet} from "../../../packages/dev-wallets/classes/DevWallet"; + + +interface devWallet { + loading: boolean, + wallets: A_Dev_Wallet[] +} + +const initialState: devWallet = { + loading: false, + wallets: [] +} + +export const loadDevWallets = createAsyncThunk( + 'devWallets/loadDevWallets', + async (_, thunkAPI) => { + const {dispatch} = thunkAPI; + dispatch(setDevWalletsLoading(true)); + const wallets = await new DevWallet().getAll(); + dispatch(setDevWalletsLoading(false)); + return wallets; + } +); + +export const createDevWallet = createAsyncThunk( + 'devWallets/createDevWallet', + async (wallet: A_Dev_Wallet, thunkAPI) => { + const {dispatch} = thunkAPI; + dispatch(setDevWalletsLoading(true)); + const savedWallet = await new DevWallet().save(wallet); + dispatch(setDevWalletsLoading(false)); + dispatch(loadDevWallets()); + return savedWallet; + } +); + +export const deleteDevWallet = createAsyncThunk( + 'devWallets/deleteDevWallet', + async (address: string, thunkAPI) => { + const {dispatch} = thunkAPI; + dispatch(setDevWalletsLoading(true)); + await new DevWallet().delete(address); + dispatch(setDevWalletsLoading(false)); + dispatch(loadDevWallets()); + } +); + + + +export const devWalletsSlice = createSlice({ + name: 'devWallets', + initialState, + reducers: { + setDevWalletsLoading: (state, action: PayloadAction ) => { + state.loading = action.payload; + }, + }, + extraReducers: (builder) => { + builder.addCase(loadDevWallets.fulfilled, (state, action: PayloadAction) => { + state.wallets = action.payload; + }); + }, +}); + +export const {setDevWalletsLoading} = devWalletsSlice.actions +export default devWalletsSlice.reducer \ No newline at end of file diff --git a/src/redux/store.ts b/src/redux/store.ts index 128e897b..692d0934 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -23,6 +23,7 @@ import connectWallet from "./wallet/actions/connectWallet"; import wallet from "./wallet/actions/wallet"; import signer from "./wallet/actions/signer"; import abiStudio from "./abi/actions/abiStudio"; +import devWallets from "./devWallets/actions/devWallets"; export const store = configureStore({ reducer: { @@ -49,7 +50,8 @@ export const store = configureStore({ connectWallet: connectWallet, wallet: wallet, signer: signer, - abiStudio: abiStudio + abiStudio: abiStudio, + devWallets: devWallets }, }); From f6e01925bdcf4d2f4a80ca5fccdf4148cd2dd3f2 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 10 Dec 2022 22:58:26 +0530 Subject: [PATCH 76/86] sign transaction using dev wallet --- src/packages/signers/adapter.ts | 11 ++++ src/packages/signers/constants/index.ts | 3 +- src/packages/signers/devWalletSigner.ts | 73 +++++++++++++++++++++++++ src/packages/signers/walletSigner.ts | 4 +- 4 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 src/packages/signers/devWalletSigner.ts diff --git a/src/packages/signers/adapter.ts b/src/packages/signers/adapter.ts index 172df32c..0bb6165c 100644 --- a/src/packages/signers/adapter.ts +++ b/src/packages/signers/adapter.ts @@ -5,12 +5,14 @@ import {BrowserAlgoSigner} from "./algoSigner"; import {LogicSigner} from "./logicSigner"; import {MyAlgoWalletSigner} from "./myAlgoWalletSigner"; import {PeraWalletSigner} from "./peraWalletSigner"; +import {DevWalletSigner} from "./devWalletSigner"; const ws = new WalletSigner(); const as = new BrowserAlgoSigner(); const ls = new LogicSigner(); const maws = new MyAlgoWalletSigner(); const ps = new PeraWalletSigner(); +const ds = new DevWalletSigner(); export function getSigner(name: string): Signer{ if (name === SIGNERS.WALLET) { @@ -28,6 +30,9 @@ export function getSigner(name: string): Signer{ else if (name === SIGNERS.PERA_WALLET) { return ps; } + else if (name === SIGNERS.DEV_WALLET) { + return ds; + } return ws; } @@ -58,6 +63,12 @@ export function getSupportedSigners(): SupportedSigner[] { label: 'Pera Wallet', instance: getSigner(SIGNERS.PERA_WALLET), logo: 'data:image/png;base64,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' + }, + { + name: SIGNERS.DEV_WALLET, + label: 'Dev Wallet', + instance: getSigner(SIGNERS.DEV_WALLET), + logo: 'data:image/png;base64,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' } ]; } \ No newline at end of file diff --git a/src/packages/signers/constants/index.ts b/src/packages/signers/constants/index.ts index 95980e0d..3888970a 100644 --- a/src/packages/signers/constants/index.ts +++ b/src/packages/signers/constants/index.ts @@ -3,7 +3,8 @@ export enum SIGNERS { ALGO_SIGNER = 'algo_signer', LOGIC_SIG = 'logic_sig', MY_ALGO_WALLET = 'my_algo_wallet', - PERA_WALLET = 'pera_wallet' + PERA_WALLET = 'pera_wallet', + DEV_WALLET = 'DEV_WALLET' } export enum ALGO_SIGNER_NET { diff --git a/src/packages/signers/devWalletSigner.ts b/src/packages/signers/devWalletSigner.ts new file mode 100644 index 00000000..a34aebaf --- /dev/null +++ b/src/packages/signers/devWalletSigner.ts @@ -0,0 +1,73 @@ +import {Signer, SignerAccount} from "./types"; +import {encodeAddress, mnemonicToSecretKey, Transaction} from "algosdk"; +import {NETWORKS} from "../core-sdk/constants"; +import {DevWallet} from "../dev-wallets/classes/DevWallet"; +import {WalletSigner} from "./walletSigner"; + + +export class DevWalletSigner implements Signer{ + private supportedNetworks: string[]; + + constructor() { + this.supportedNetworks = [NETWORKS.SANDBOX, NETWORKS.BETANET, NETWORKS.TESTNET]; + } + + async signTxn(unsignedTxn: Transaction): Promise { + const {from} = unsignedTxn; + const address = encodeAddress(from.publicKey); + + const devWallet = await new DevWallet().get(address); + + const {mnemonic} = devWallet; + const account = mnemonicToSecretKey(mnemonic); + + const wSigner = new WalletSigner(account); + return wSigner.signTxn(unsignedTxn); + } + + async signGroupTxns(unsignedTxns: Transaction[]): Promise { + const proms = []; + unsignedTxns.forEach((unsignedTxn) => { + proms.push(this.signTxn(unsignedTxn)); + }); + + return await Promise.all(proms); + } + + async connect(name: string): Promise { + if (this.isInstalled()) { + if (this.isNetworkSupported(name)) { + const accounts: SignerAccount[] = []; + const wallets = await new DevWallet().getAll(); + if (wallets) { + wallets.forEach((wallet) => { + accounts.push({ + address: wallet.address, + name: wallet.address + }); + }); + } + + return accounts; + } + else { + throw new Error(name + " is not supported by Dev Wallet"); + } + } + else { + throw new Error("Dev Wallet is not installed"); + } + } + + isInstalled(): boolean { + return true; + } + + isNetworkSupported(name: string): boolean { + return this.supportedNetworks.indexOf(name) !== -1; + } + + logout() { + + } +} \ No newline at end of file diff --git a/src/packages/signers/walletSigner.ts b/src/packages/signers/walletSigner.ts index 89a26e3e..129943fa 100644 --- a/src/packages/signers/walletSigner.ts +++ b/src/packages/signers/walletSigner.ts @@ -27,8 +27,8 @@ export class WalletSigner implements Signer{ const signedTxns: Uint8Array[] = []; unsignedTxns.forEach((unsignedTxn) => { - const test = this.signTxn(unsignedTxn); - signedTxns.push(test); + const signedTxn = this.signTxn(unsignedTxn); + signedTxns.push(signedTxn); }); return signedTxns; From 78c02c25f930baeb0ee6dc58d52cc52c2165b3c3 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sat, 10 Dec 2022 23:37:18 +0530 Subject: [PATCH 77/86] dev wallet actions --- .../DevWallets/DevWallets/DevWallets.tsx | 36 ++++++++++++++++--- .../AppCallTxnReturnValue.scss | 1 + 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx index 4b082315..5cfe3ff1 100644 --- a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx @@ -3,11 +3,12 @@ import React, {useEffect} from "react"; import {useDispatch, useSelector} from "react-redux"; import AddIcon from "@mui/icons-material/Add"; import {Button} from "@mui/material"; -import {shadedClr} from "../../../../utils/common"; +import {copyContent, shadedClr} from "../../../../utils/common"; import {createDevWallet, deleteDevWallet, loadDevWallets} from "../../../../redux/devWallets/actions/devWallets"; import {generateAccount, secretKeyToMnemonic} from 'algosdk' import {A_Dev_Wallet} from "../../../../packages/dev-wallets/types"; import {RootState} from "../../../../redux/store"; +import {showSnack} from "../../../../redux/common/actions/snackbar"; function DevWallets(): JSX.Element { @@ -15,6 +16,7 @@ function DevWallets(): JSX.Element { const dispatch = useDispatch(); const devWallets = useSelector((state: RootState) => state.devWallets); + const wallet = useSelector((state: RootState) => state.wallet); const {wallets} = devWallets; @@ -55,18 +57,42 @@ function DevWallets(): JSX.Element {
- {wallets.map((wallet) => { - return
+ {wallets.map((devWallet) => { + return
- {wallet.address} + {devWallet.address} +
+ + +
diff --git a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss index eb09811e..40f4605f 100644 --- a/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss +++ b/src/components/Modules/Explorer/Records/Transaction/Types/AppCallTransaction/Sections/AppCallTxnReturnValue/AppCallTxnReturnValue.scss @@ -18,6 +18,7 @@ } .method-sig-section-value { font-weight: bold; + word-break: break-all; font-family: PoppinsLight !important; * { font-family: PoppinsLight !important; From 1ac24f2c5898bb1077749ab78dd7f585e3951173 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 11 Dec 2022 00:02:03 +0530 Subject: [PATCH 78/86] support bare app deployments --- .../Modules/ABI/ABIEditor/ABIEditor.tsx | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx index aff9fb88..5d475afe 100644 --- a/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx +++ b/src/components/Modules/ABI/ABIEditor/ABIEditor.tsx @@ -12,6 +12,7 @@ import {A_AccountInformation} from "../../../../packages/core-sdk/types"; import {defaultAccount} from "../../../../redux/wallet/actions/wallet"; import ABIMethodExecutor from "../ABIMethodExecutor/ABIMethodExecutor"; import {KeyboardArrowDown} from "@mui/icons-material"; +import CreateApp from "../../AppManager/CreateApp/CreateApp"; type ABIEditorProps = { abi: ABIContractParams, @@ -25,6 +26,7 @@ type ABIEditorProps = { interface ABIEditorState{ showConfig: boolean, showCreateApp: boolean, + showBareCreateApp: boolean, method: ABIMethodParams } @@ -41,6 +43,7 @@ const defaultMethod = { const initialState: ABIEditorState = { showConfig: false, showCreateApp: false, + showBareCreateApp: false, method: defaultMethod }; @@ -56,7 +59,7 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support }; const [ - {showCreateApp, method}, + {showCreateApp, method, showBareCreateApp}, setState ] = useState(initialState); @@ -132,11 +135,27 @@ function ABIEditor({abi = {methods: [], name: ""}, hideNetworks = false, support ; })} + { + setState(prevState => ({...prevState, showBareCreateApp: true})); + closeCreateAppMenu(); + e.preventDefault(); + e.stopPropagation(); + } + }> + Bare + + { setState(prevState => ({...prevState, method: defaultMethod, showCreateApp: false})); }} account={account}> + + { + setState(prevState => ({...prevState, showBareCreateApp: false})); + }}> From 7b11c87412f5c3037ec8bd293631c671d99f3ccc Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 11 Dec 2022 00:30:19 +0530 Subject: [PATCH 79/86] manage dev wallets --- .../Modules/ABI/ImportABI/ImportABI.tsx | 5 + .../DevWallets/DevWallets/DevWallets.scss | 8 +- .../DevWallets/DevWallets/DevWallets.tsx | 160 +++++++++++------- 3 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/components/Modules/ABI/ImportABI/ImportABI.tsx b/src/components/Modules/ABI/ImportABI/ImportABI.tsx index 102378fe..d06c63a6 100644 --- a/src/components/Modules/ABI/ImportABI/ImportABI.tsx +++ b/src/components/Modules/ABI/ImportABI/ImportABI.tsx @@ -177,6 +177,11 @@ function ImportABI(props): JSX.Element { sx={{marginLeft: '10px'}} > + { + setState(prevState => ({...prevState, url: "https://raw.githubusercontent.com/algorand-devrel/beaker-calculator/main/calculator-pyteal/contract.json"})); + }} label="Calculator ABI" size="small" color={"warning"} variant={"outlined"} + sx={{marginLeft: '10px'}} + >
diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.scss b/src/components/Modules/DevWallets/DevWallets/DevWallets.scss index 9d6ff6fe..980dfb58 100644 --- a/src/components/Modules/DevWallets/DevWallets/DevWallets.scss +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.scss @@ -28,9 +28,11 @@ padding: 20px; display: flex; justify-content: space-between; - .wallet-address { - font-size: 13px; - font-weight: bold; + .wallet-details { + .wallet-address { + font-size: 13px; + font-weight: bold; + } } .wallet-actions { diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx index 5cfe3ff1..607aa0b1 100644 --- a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx @@ -9,7 +9,11 @@ import {generateAccount, secretKeyToMnemonic} from 'algosdk' import {A_Dev_Wallet} from "../../../../packages/dev-wallets/types"; import {RootState} from "../../../../redux/store"; import {showSnack} from "../../../../redux/common/actions/snackbar"; - +import {CoreNode} from "../../../../packages/core-sdk/classes/core/CoreNode"; +import {Alert} from "@mui/lab"; +import DeleteIcon from '@mui/icons-material/Delete'; +import OpenInNewIcon from '@mui/icons-material/OpenInNew'; +import ContentCopyIcon from '@mui/icons-material/ContentCopy'; function DevWallets(): JSX.Element { @@ -19,6 +23,11 @@ function DevWallets(): JSX.Element { const wallet = useSelector((state: RootState) => state.wallet); const {wallets} = devWallets; + const node = useSelector((state: RootState) => state.node); + const {versionsCheck, status, genesis, health} = node; + const coreNodeInstance = new CoreNode(status, versionsCheck, genesis, health); + const isMainnet = coreNodeInstance.isMainnet(); + useEffect(() => { dispatch(loadDevWallets()); @@ -34,74 +43,103 @@ function DevWallets(): JSX.Element {
-
-
- + + {isMainnet ?
+ + For security reasons, This feature is not available for this network ({coreNodeInstance.getGenesisId()}) + +
:
+
+
+ + Use these wallets only for development purpose. Private keys of these wallets are stored on your local browser to sign the txns later in ABI studio. + These wallets are not secured properly, So please use these wallets carefully and Dappflow is not responsible for any loss of funds. For security reasons this feature is not available for mainnet. + + + +
-
-
-
- {wallets.map((devWallet) => { - return
-
-
- {devWallet.address} -
- + +
+
+
+ - + >Delete
-
- -
-
-
; - })} +
; + })} + +
+
: ''} + +
} -
-
); From 9477fc8617c5f79a8f27564e399b6ccd50590d15 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 11 Dec 2022 15:29:00 +0530 Subject: [PATCH 80/86] ability to dispense algos for a dev wallet when connected to sandbox --- .../DevWallets/DevWallets/DevWallets.tsx | 59 ++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx index 607aa0b1..d648b393 100644 --- a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx @@ -5,7 +5,7 @@ import AddIcon from "@mui/icons-material/Add"; import {Button} from "@mui/material"; import {copyContent, shadedClr} from "../../../../utils/common"; import {createDevWallet, deleteDevWallet, loadDevWallets} from "../../../../redux/devWallets/actions/devWallets"; -import {generateAccount, secretKeyToMnemonic} from 'algosdk' +import algosdk, {generateAccount, secretKeyToMnemonic, SuggestedParams, waitForConfirmation} from 'algosdk' import {A_Dev_Wallet} from "../../../../packages/dev-wallets/types"; import {RootState} from "../../../../redux/store"; import {showSnack} from "../../../../redux/common/actions/snackbar"; @@ -14,6 +14,13 @@ import {Alert} from "@mui/lab"; import DeleteIcon from '@mui/icons-material/Delete'; import OpenInNewIcon from '@mui/icons-material/OpenInNew'; import ContentCopyIcon from '@mui/icons-material/ContentCopy'; +import {hideLoader, showLoader} from "../../../../redux/common/actions/loader"; +import {KmdClient} from "../../../../packages/core-sdk/clients/kmdClient"; +import dappflow from "../../../../utils/dappflow"; +import {KMDConnectionParams} from "../../../../packages/core-sdk/types"; +import {getKMDConfig} from "../../../../utils/nodeConfig"; +import {handleException} from "../../../../redux/common/actions/exception"; +import ShowerIcon from "@mui/icons-material/Shower"; function DevWallets(): JSX.Element { @@ -27,6 +34,7 @@ function DevWallets(): JSX.Element { const {versionsCheck, status, genesis, health} = node; const coreNodeInstance = new CoreNode(status, versionsCheck, genesis, health); const isMainnet = coreNodeInstance.isMainnet(); + const isSandbox = coreNodeInstance.isSandbox(); useEffect(() => { @@ -111,6 +119,55 @@ function DevWallets(): JSX.Element { copyContent(event, dispatch, devWallet.address, 'Address copied'); }} >Copy + + {isSandbox ? : ''} +
From e96cec2fb4bdcb65329717faff5d52aa1b9ca52f Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 11 Dec 2022 18:00:28 +0530 Subject: [PATCH 81/86] dev wallet management --- .../DevWallets/DevWallets/DevWallets.scss | 11 ++++ .../DevWallets/DevWallets/DevWallets.tsx | 13 +++- .../Common/AccountBalance/AccountBalance.scss | 7 +++ .../Common/AccountBalance/AccountBalance.tsx | 59 +++++++++++++++++++ src/packages/dev-wallets/classes/DevWallet.ts | 2 +- src/redux/devWallets/actions/devWallets.ts | 3 +- 6 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/components/Modules/Explorer/Common/AccountBalance/AccountBalance.scss create mode 100644 src/components/Modules/Explorer/Common/AccountBalance/AccountBalance.tsx diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.scss b/src/components/Modules/DevWallets/DevWallets/DevWallets.scss index 980dfb58..cdb36869 100644 --- a/src/components/Modules/DevWallets/DevWallets/DevWallets.scss +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.scss @@ -32,6 +32,17 @@ .wallet-address { font-size: 13px; font-weight: bold; + .wallet-balance { + margin-top: 10px; + .account-balance-wrapper { + .account-balance-container { + img { + width: 12px !important; + margin-left: 5px; + } + } + } + } } } .wallet-actions { diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx index d648b393..c7b6f739 100644 --- a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx @@ -4,7 +4,12 @@ import {useDispatch, useSelector} from "react-redux"; import AddIcon from "@mui/icons-material/Add"; import {Button} from "@mui/material"; import {copyContent, shadedClr} from "../../../../utils/common"; -import {createDevWallet, deleteDevWallet, loadDevWallets} from "../../../../redux/devWallets/actions/devWallets"; +import { + createDevWallet, + deleteDevWallet, + loadDevWallets, + resetDevWallets +} from "../../../../redux/devWallets/actions/devWallets"; import algosdk, {generateAccount, secretKeyToMnemonic, SuggestedParams, waitForConfirmation} from 'algosdk' import {A_Dev_Wallet} from "../../../../packages/dev-wallets/types"; import {RootState} from "../../../../redux/store"; @@ -21,6 +26,7 @@ import {KMDConnectionParams} from "../../../../packages/core-sdk/types"; import {getKMDConfig} from "../../../../utils/nodeConfig"; import {handleException} from "../../../../redux/common/actions/exception"; import ShowerIcon from "@mui/icons-material/Shower"; +import AccountBalance from "../../Explorer/Common/AccountBalance/AccountBalance"; function DevWallets(): JSX.Element { @@ -100,6 +106,9 @@ function DevWallets(): JSX.Element {
{devWallet.address} +
+ +
); From 7a6c76d955c29279c788ac0a8411ca71f5ead9b9 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 11 Dec 2022 21:03:39 +0530 Subject: [PATCH 83/86] dev wallet delete confirmation --- package.json | 1 + .../DevWallets/DevWallets/DevWallets.tsx | 21 ++++++++++++++++++- src/index.tsx | 5 ++++- yarn.lock | 5 +++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 346a3abb..b1a8b0f8 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "is-utf8": "^0.2.1", "js-sha512": "^0.8.0", "markdown-to-jsx": "^7.1.7", + "material-ui-confirm": "^3.0.7", "msgpack-lite": "^0.1.26", "mui-markdown": "^0.5.5", "multiformats": "^9.7.1", diff --git a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx index 6ce667fb..cba085b9 100644 --- a/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx +++ b/src/components/Modules/DevWallets/DevWallets/DevWallets.tsx @@ -27,6 +27,7 @@ import {getKMDConfig} from "../../../../utils/nodeConfig"; import {handleException} from "../../../../redux/common/actions/exception"; import ShowerIcon from "@mui/icons-material/Shower"; import AccountBalance from "../../Explorer/Common/AccountBalance/AccountBalance"; +import { useConfirm } from "material-ui-confirm"; function DevWallets(): JSX.Element { @@ -42,6 +43,8 @@ function DevWallets(): JSX.Element { const isMainnet = coreNodeInstance.isMainnet(); const isSandbox = coreNodeInstance.isSandbox(); + const confirm = useConfirm(); + useEffect(() => { dispatch(loadDevWallets()); @@ -193,7 +196,23 @@ function DevWallets(): JSX.Element { return; } - dispatch(deleteDevWallet(devWallet.address)); + confirm({ + description: "You are trying to delete a wallet and this action cannot be reversed.", + confirmationText: 'Delete', + confirmationButtonProps: { + color: 'warning', + variant: 'outlined', + size: 'small' + }, + cancellationButtonProps: { + color: 'inherit', + size: 'small' + } + }) + .then(() => { + dispatch(deleteDevWallet(devWallet.address)); + }) + .catch(() => {}); }} >Delete
diff --git a/src/index.tsx b/src/index.tsx index 91a918f3..a28f9f68 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -6,12 +6,15 @@ import {theme} from "./theme"; import { store } from './redux/store'; import { Provider } from 'react-redux'; import App from "./components/App/App"; +import { ConfirmProvider } from "material-ui-confirm"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - + + + ); diff --git a/yarn.lock b/yarn.lock index 233a94e0..495fd89f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7850,6 +7850,11 @@ markdown-to-jsx@^7.1.7: resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.1.7.tgz#a5f22102fb12241c8cea1ca6a4050bb76b23a25d" integrity sha512-VI3TyyHlGkO8uFle0IOibzpO1c1iJDcXcS/zBrQrXQQvJ2tpdwVzVZ7XdKsyRz1NdRmre4dqQkMZzUHaKIG/1w== +material-ui-confirm@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/material-ui-confirm/-/material-ui-confirm-3.0.7.tgz#7111600f6bb144b040878e995c83165dab8114b7" + integrity sha512-HZkym2nYSdKAmcCVtj/N/ygwWz/mlbWLrLAY6oRxBvD4Z1JBEmBNC//4yGAiNKlR0/9BlC6GKdY5RnqUaTwSKA== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" From 1ab148b43c9243d1c64ffe59db3559c5798b4c28 Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 11 Dec 2022 21:12:10 +0530 Subject: [PATCH 84/86] bug fix --- src/components/Modules/AppManager/CreateApp/CreateApp.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 00f15edb..5663f761 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -239,7 +239,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n dispatch(showLoader('Waiting for confirmation')); await appCallInstance.waitForConfirmation(txId); const txn = await new TransactionClient(dappflow.network).get(txId); - dispatch(hideLoader()); + const txnInstance = new CoreTransaction(txn); dispatch(updateAppId(txnInstance.getAppId().toString())); @@ -249,6 +249,7 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n severity: 'success', message: 'Application created successfully. You can execute the ABI calls.' })); + dispatch(hideLoader()); } catch (e: any) { dispatch(hideLoader()); From 3488fb98bee3c24343eae1d797fb3ef6e7b3847f Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Sun, 11 Dec 2022 21:35:47 +0530 Subject: [PATCH 85/86] compile program handle error gracefully --- .../ABIMethodExecutor/ABIMethodExecutor.tsx | 20 +++++++++++-------- .../AppManager/CreateApp/CreateApp.tsx | 20 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx index 11798d63..bc924d0e 100644 --- a/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx +++ b/src/components/Modules/ABI/ABIMethodExecutor/ABIMethodExecutor.tsx @@ -461,10 +461,12 @@ function ABIMethodExecutor({show = false, creation = false, method = { style={{ display: "none" }} onChange={async (event) => { const compileResponse = await validateProgram(event); - setState(prevState => ({...prevState, creationParams: { - ...creationParams, - approvalProgram: compileResponse.result - }})); + if (compileResponse) { + setState(prevState => ({...prevState, creationParams: { + ...creationParams, + approvalProgram: compileResponse.result + }})); + } }} /> @@ -491,10 +493,12 @@ function ABIMethodExecutor({show = false, creation = false, method = { style={{ display: "none" }} onChange={async (event) => { const compileResponse = await validateProgram(event); - setState(prevState => ({...prevState, creationParams: { - ...creationParams, - clearProgram: compileResponse.result - }})); + if (compileResponse) { + setState(prevState => ({...prevState, creationParams: { + ...creationParams, + clearProgram: compileResponse.result + }})); + } }} /> {creationParams.clearProgram ?
diff --git a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx index 5663f761..6776d70d 100644 --- a/src/components/Modules/AppManager/CreateApp/CreateApp.tsx +++ b/src/components/Modules/AppManager/CreateApp/CreateApp.tsx @@ -417,10 +417,12 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n style={{ display: "none" }} onChange={async (event) => { const compileResponse = await validateProgram(event); - setState(prevState => ({...prevState, params: { - ...params, - approvalProgram: compileResponse.result - }})); + if (compileResponse) { + setState(prevState => ({...prevState, params: { + ...params, + approvalProgram: compileResponse.result + }})); + } }} /> @@ -447,10 +449,12 @@ function CreateApp({show = defaultProps.show, handleClose, abi = {methods: [], n style={{ display: "none" }} onChange={async (event) => { const compileResponse = await validateProgram(event); - setState(prevState => ({...prevState, params: { - ...params, - clearProgram: compileResponse.result - }})); + if (compileResponse) { + setState(prevState => ({...prevState, params: { + ...params, + clearProgram: compileResponse.result + }})); + } }} /> {params.clearProgram ?
From eb6590b13915157968e5a5fd818f01057226b43e Mon Sep 17 00:00:00 2001 From: shiva prasad manupadi Date: Mon, 12 Dec 2022 22:24:30 +0530 Subject: [PATCH 86/86] show abi studio only after abi is imported --- src/components/Modules/ABI/ABIStudio/ABIStudio.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx index 1939afb2..1ff9eca1 100644 --- a/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx +++ b/src/components/Modules/ABI/ABIStudio/ABIStudio.tsx @@ -32,7 +32,7 @@ function ABIStudio(): JSX.Element { { dispatch(updateAbi(abi)); }}> - {abi ? : ''} + {abi.name ? : ''}