Skip to content

Commit

Permalink
[ENG-3844][ENG-3845][ENG-3850][ENG-3851] stx_callContract, stx_transf…
Browse files Browse the repository at this point in the history
…erStx, stx_getAccounts, stx_getAddresses (#112)

* Add placeholders for stx rpc handlers

* Move helpers to own file

* Remove unused

* Add various changes related to request handling

* Add rpc method param for transaction request type differentiation

* Add response message

* Add rpc method to request params

* Provide rpc response based on rpc call method

* Handle missing function args

* Move error messages to constants

* Add missing rpc method

* Remove unnecessary type

* Refine variable name

* Prevent unknown errors from blocking navigation

* Add rpc props

* Remove unnecessary conditional

* Send rpc response after broadcast

* Start updating ContractCall to RPC request

* Handle contract deploy request

* Update rpc response type

* Add rpc props

* Remove sign message work from this branch

* Simplify request handling

* Rename file

* Add handler and helpers for contractCall

* Rename handler file

* Update hook to handle callContract

* Perform minor tweaks for callContract

* fix: updated sats connect version and stacks methods names

* feat: handle stx_transferStx method

* Use Zod union

* Fix minor issues

* Add stx_getAccounts and stx_getAddresses method handlers

* Update the handleGetStxAccounts method

* Update types

* Remove unimplemented methods

* Refactor send message helpers

* Update params type

* Remove unused prop

* Move messages to translation file

* Add useMemo and useCallback to accounts and address fetching hooks

* Refactor the getAppIconFromWebManifest fetching

* Refactor the getAppIconFromWebManifest fetching useEffect

* Use existing payload format

* Move hook close to component using it

* Replace the ternary return with if statement

---------

Co-authored-by: Abdul Haseeb <haseeb4239@gmail.com>
Co-authored-by: Denys Hriaznov <hriaznov.dev@gmail.com>
  • Loading branch information
3 people authored Mar 7, 2024
1 parent ec067cd commit 440c1eb
Show file tree
Hide file tree
Showing 41 changed files with 1,583 additions and 948 deletions.
740 changes: 29 additions & 711 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"stream-browserify": "^3.0.0",
"string-to-color": "^2.2.2",
"styled-components": "^5.3.5",
"superjson": "2.2.1",
"swiper": "11.0.6",
"ts-transformer-keys": "^0.4.4",
"valid-url": "^1.0.9",
Expand Down
154 changes: 116 additions & 38 deletions src/app/components/transactionsRequests/ContractCallRequest.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import {
sendCallContractSuccessResponseMessage,
sendInternalErrorMessage,
sendSignTransactionSuccessResponseMessage,
sendUserRejectionMessage,
} from '@common/utils/rpc/stx/rpcResponseMessages';
import AccountHeaderComponent from '@components/accountHeader';
import ConfirmStxTransactionComponent from '@components/confirmStxTransactionComponent';
import InfoContainer from '@components/infoContainer';
Expand All @@ -8,24 +14,24 @@ import TransactionDetailComponent from '@components/transactionDetailComponent';
import useNetworkSelector from '@hooks/useNetwork';
import useOnOriginTabClose from '@hooks/useOnTabClosed';
import {
addressToString,
Args,
broadcastSignedTransaction,
buf2hex,
Coin,
ContractFunction,
addressToString,
broadcastSignedTransaction,
buf2hex,
extractFromPayload,
isMultiSig,
} from '@secretkeylabs/xverse-core';
import { ContractCallPayload } from '@stacks/connect';
import {
ClarityType,
cvToJSON,
cvToString,
MultiSigSpendingCondition,
PostConditionType,
SomeCV,
StacksTransaction,
cvToJSON,
cvToString,
} from '@stacks/transactions';
import { createContext, useState } from 'react';
import { useTranslation } from 'react-i18next';
Expand Down Expand Up @@ -75,15 +81,26 @@ interface ContractCallRequestProps {
funcMetaData: ContractFunction | undefined;
coinsMetaData: Coin[] | null;
tabId: number;
messageId: string | null;
rpcMethod: string | null;
requestToken: string;
attachment: Buffer | undefined;
}

export const ShowMoreContext = createContext({ showMore: false });

export default function ContractCallRequest(props: ContractCallRequestProps) {
const { request, unsignedTx, funcMetaData, coinsMetaData, tabId, requestToken, attachment } =
props;
const {
request,
unsignedTx,
funcMetaData,
coinsMetaData,
tabId,
requestToken,
attachment,
messageId,
rpcMethod,
} = props;
const selectedNetwork = useNetworkSelector();
const [hasTabClosed, setHasTabClosed] = useState(false);
const { t } = useTranslation('translation');
Expand Down Expand Up @@ -175,61 +192,122 @@ export default function ContractCallRequest(props: ContractCallRequestProps) {
txAttachment: Buffer | undefined = undefined,
) => {
try {
const broadcastResult: string = await broadcastSignedTransaction(
tx[0],
selectedNetwork,
txAttachment,
);
if (broadcastResult) {
const txId = await broadcastSignedTransaction(tx[0], selectedNetwork, txAttachment);
if (tabId && messageId && rpcMethod) {
switch (rpcMethod) {
case 'stx_signTransaction': {
sendSignTransactionSuccessResponseMessage({
tabId,
messageId,
result: { transaction: buf2hex(tx[0].serialize()) },
});
break;
}
case 'stx_callContract': {
sendCallContractSuccessResponseMessage({
tabId,
messageId,
result: {
transaction: buf2hex(tx[0].serialize()),
txid: txId,
},
});
break;
}
default: {
sendInternalErrorMessage({ tabId, messageId });
}
}
} else {
finalizeTxSignature({
requestPayload: requestToken,
tabId,
data: { txId: broadcastResult, txRaw: buf2hex(tx[0].serialize()) },
});
navigate('/tx-status', {
state: {
txid: broadcastResult,
currency: 'STX',
error: '',
browserTx: true,
},
data: { txId, txRaw: buf2hex(tx[0].serialize()) },
});
}
navigate('/tx-status', {
state: {
txid: txId,
currency: 'STX',
error: '',
browserTx: true,
tabId,
messageId,
rpcMethod,
},
});
} catch (e) {
if (e instanceof Error) {
navigate('/tx-status', {
state: {
txid: '',
currency: 'STX',
error: e.message,
browserTx: true,
},
});
}
sendInternalErrorMessage({ tabId, messageId });
navigate('/tx-status', {
state: {
txid: '',
currency: 'STX',
error: e instanceof Error ? e.message : 'An error occurred',
browserTx: true,
tabId,
messageId,
rpcMethod,
},
});
}
};

const confirmCallback = (transactions: StacksTransaction[]) => {
if (request?.sponsored) {
if (rpcMethod && tabId && messageId) {
switch (rpcMethod) {
case 'stx_signTransaction': {
sendSignTransactionSuccessResponseMessage({
tabId,
messageId,
result: { transaction: buf2hex(unsignedTx.serialize()) },
});
break;
}
default: {
sendInternalErrorMessage({ tabId, messageId });
}
}
}
navigate('/tx-status', {
state: {
sponsored: true,
browserTx: true,
},
});
} else if (isMultiSigTx) {
finalizeTxSignature({
requestPayload: requestToken,
tabId,
data: { txId: '', txRaw: buf2hex(unsignedTx.serialize()) },
});
if (rpcMethod && tabId && messageId) {
switch (rpcMethod) {
case 'stx_signTransaction': {
sendSignTransactionSuccessResponseMessage({
tabId,
messageId,
result: { transaction: buf2hex(unsignedTx.serialize()) },
});
break;
}
default: {
sendInternalErrorMessage({ tabId, messageId });
}
}
} else {
finalizeTxSignature({
requestPayload: requestToken,
tabId,
data: { txId: '', txRaw: buf2hex(unsignedTx.serialize()) },
});
}
window.close();
} else {
broadcastTx(transactions, attachment);
}
};
const cancelCallback = () => {
finalizeTxSignature({ requestPayload: requestToken, tabId, data: 'cancel' });
if (tabId && messageId) {
sendUserRejectionMessage({ tabId, messageId });
} else {
finalizeTxSignature({ requestPayload: requestToken, tabId, data: 'cancel' });
}
window.close();
};

Expand Down
106 changes: 87 additions & 19 deletions src/app/components/transactionsRequests/ContractDeployTransaction.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import DownloadImage from '@assets/img/webInteractions/ArrowLineDown.svg';
import {
sendInternalErrorMessage,
sendSignTransactionSuccessResponseMessage,
sendUserRejectionMessage,
} from '@common/utils/rpc/stx/rpcResponseMessages';
import AccountHeaderComponent from '@components/accountHeader';
import ConfirmStxTransactionComponent from '@components/confirmStxTransactionComponent';
import InfoContainer from '@components/infoContainer';
Expand Down Expand Up @@ -101,10 +106,21 @@ interface ContractDeployRequestProps {
sponsored: boolean;
tabId: number;
requestToken: string;
messageId: string | null;
rpcMethod: string | null;
}

export default function ContractDeployRequest(props: ContractDeployRequestProps) {
const { unsignedTx, codeBody, contractName, sponsored, tabId, requestToken } = props;
const {
unsignedTx,
codeBody,
contractName,
sponsored,
tabId,
requestToken,
messageId,
rpcMethod,
} = props;
const selectedNetwork = useNetworkSelector();
const [hasTabClosed, setHasTabClosed] = useState(false);
const { t } = useTranslation('translation');
Expand All @@ -125,26 +141,41 @@ export default function ContractDeployRequest(props: ContractDeployRequestProps)
const broadcastTx = async (tx: StacksTransaction[]) => {
try {
setLoaderForBroadcastingTx(true);
const broadcastResult = await broadcastSignedTransaction(tx[0], selectedNetwork);
if (broadcastResult) {
const txId = await broadcastSignedTransaction(tx[0], selectedNetwork);
if (rpcMethod && messageId && tabId) {
switch (rpcMethod) {
case 'stx_signTransaction':
sendSignTransactionSuccessResponseMessage({
tabId,
messageId,
result: { transaction: buf2hex(tx[0].serialize()) },
});
break;
default:
sendInternalErrorMessage({ tabId, messageId });
break;
}
} else {
finalizeTxSignature({
requestPayload: requestToken,
tabId,
data: { txId: broadcastResult, txRaw: buf2hex(tx[0].serialize()) },
});
navigate('/tx-status', {
state: {
txid: broadcastResult,
currency: 'STX',
error: '',
browserTx: true,
tabId,
requestToken,
},
data: { txId, txRaw: buf2hex(tx[0].serialize()) },
});
}

navigate('/tx-status', {
state: {
txid: txId,
currency: 'STX',
error: '',
browserTx: true,
tabId,
requestToken,
},
});
} catch (error: any) {
setLoaderForBroadcastingTx(false);
sendInternalErrorMessage({ tabId, messageId });
navigate('/tx-status', {
state: {
txid: '',
Expand All @@ -160,18 +191,52 @@ export default function ContractDeployRequest(props: ContractDeployRequestProps)

const confirmCallback = (txs: StacksTransaction[]) => {
if (sponsored) {
if (rpcMethod && messageId && tabId) {
switch (rpcMethod) {
case 'stx_signTransaction':
sendSignTransactionSuccessResponseMessage({
tabId,
messageId,
result: { transaction: buf2hex(unsignedTx.serialize()) },
});
break;
default:
sendInternalErrorMessage({ tabId, messageId });
break;
}
sendSignTransactionSuccessResponseMessage({
tabId,
messageId,
result: { transaction: buf2hex(unsignedTx.serialize()) },
});
}
navigate('/tx-status', {
state: {
sponsored: true,
browserTx: true,
},
});
} else if (isMultiSigTx) {
finalizeTxSignature({
requestPayload: requestToken,
tabId,
data: { txId: '', txRaw: buf2hex(unsignedTx.serialize()) },
});
if (rpcMethod && messageId && tabId) {
switch (rpcMethod) {
case 'stx_signTransaction':
sendSignTransactionSuccessResponseMessage({
tabId,
messageId,
result: { transaction: buf2hex(unsignedTx.serialize()) },
});
break;
default:
sendInternalErrorMessage({ tabId, messageId });
break;
}
} else {
finalizeTxSignature({
requestPayload: requestToken,
tabId,
data: { txId: '', txRaw: buf2hex(unsignedTx.serialize()) },
});
}
window.close();
} else {
broadcastTx(txs);
Expand All @@ -188,6 +253,9 @@ export default function ContractDeployRequest(props: ContractDeployRequestProps)
};

const cancelCallback = () => {
if (rpcMethod && messageId && tabId) {
sendUserRejectionMessage({ tabId, messageId });
}
finalizeTxSignature({ requestPayload: requestToken, tabId, data: 'cancel' });
window.close();
};
Expand Down
Loading

0 comments on commit 440c1eb

Please sign in to comment.