Skip to content

Commit

Permalink
[Issue-3132] feat: handle sign and approve send cardano
Browse files Browse the repository at this point in the history
  • Loading branch information
bluezdot committed Nov 29, 2024
1 parent 35a9b9e commit 5be20c9
Show file tree
Hide file tree
Showing 19 changed files with 634 additions and 33 deletions.
33 changes: 31 additions & 2 deletions packages/extension-base/src/background/KoniTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TransactionError } from '@subwallet/extension-base/background/errors/Tr
import { Resolver } from '@subwallet/extension-base/background/handlers/State';
import { AccountAuthType, AuthorizeRequest, ConfirmationRequestBase, RequestAccountList, RequestAccountSubscribe, RequestAccountUnsubscribe, RequestAuthorizeCancel, RequestAuthorizeReject, RequestAuthorizeSubscribe, RequestAuthorizeTab, RequestCurrentAccountAddress, ResponseAuthorizeList } from '@subwallet/extension-base/background/types';
import { RequestOptimalTransferProcess } from '@subwallet/extension-base/services/balance-service/helpers';
import { CardanoTransactionConfig } from '@subwallet/extension-base/services/balance-service/transfer/cardano-transfer';
import { TonTransactionConfig } from '@subwallet/extension-base/services/balance-service/transfer/ton-transfer';
import { _CHAIN_VALIDATION_ERROR } from '@subwallet/extension-base/services/chain-service/handler/types';
import { _ChainState, _EvmApi, _NetworkUpsertParams, _SubstrateApi, _ValidateCustomAssetRequest, _ValidateCustomAssetResponse, EnableChainParams, EnableMultiChainParams } from '@subwallet/extension-base/services/chain-service/types';
Expand Down Expand Up @@ -1069,6 +1070,12 @@ export interface TonSignRequest {
canSign: boolean;
}

export interface CardanoSignRequest {
account: AccountJson;
hashPayload: string;
canSign: boolean;
}

export interface ErrorValidation {
message: string;
name: string;
Expand All @@ -1087,6 +1094,12 @@ export interface TonSignatureRequest extends TonSignRequest {
payload: unknown;
}

export interface CardanoSignatureRequest extends CardanoSignRequest {
id: string;
type: string;
payload: unknown
}

export interface EvmSendTransactionRequest extends TransactionConfig, EvmSignRequest {
estimateGas: string;
parseData: EvmTransactionData;
Expand All @@ -1096,9 +1109,11 @@ export interface EvmSendTransactionRequest extends TransactionConfig, EvmSignReq

// TODO: add account info + dataToSign
export type TonSendTransactionRequest = TonTransactionConfig;
export type CardanoSendTransactionRequest = CardanoTransactionConfig;

export type EvmWatchTransactionRequest = EvmSendTransactionRequest;
export type TonWatchTransactionRequest = TonSendTransactionRequest;
export type CardanoWatchTransactionRequest = CardanoSendTransactionRequest;

export interface ConfirmationsQueueItemOptions {
requiredPassword?: boolean;
Expand Down Expand Up @@ -1164,28 +1179,40 @@ export interface ConfirmationDefinitionsTon {
tonWatchTransactionRequest: [ConfirmationsQueueItem<TonWatchTransactionRequest>, ConfirmationResult<string>]
}

export interface ConfirmationDefinitionsCardano {
cardanoSignatureRequest: [ConfirmationsQueueItem<CardanoSignatureRequest>, ConfirmationResult<string>],
cardanoSendTransactionRequest: [ConfirmationsQueueItem<CardanoSendTransactionRequest>, ConfirmationResult<string>],
cardanoWatchTransactionRequest: [ConfirmationsQueueItem<CardanoWatchTransactionRequest>, ConfirmationResult<string>]
}

export type ConfirmationType = keyof ConfirmationDefinitions;
export type ConfirmationTypeTon = keyof ConfirmationDefinitionsTon;
export type ConfirmationTypeCardano = keyof ConfirmationDefinitionsCardano;

export type ConfirmationsQueue = {
[CT in ConfirmationType]: Record<string, ConfirmationDefinitions[CT][0]>;
}
export type ConfirmationsQueueTon = {
[CT in ConfirmationTypeTon]: Record<string, ConfirmationDefinitionsTon[CT][0]>;
}
export type ConfirmationsQueueCardano = {
[CT in ConfirmationTypeCardano]: Record<string, ConfirmationDefinitionsCardano[CT][0]>;
}

export type RequestConfirmationsSubscribe = null;

export type RequestConfirmationsSubscribeTon = null;
export type RequestConfirmationsSubscribeCardano = null;

// Design to use only one confirmation
export type RequestConfirmationComplete = {
[CT in ConfirmationType]?: ConfirmationDefinitions[CT][1];
}

export type RequestConfirmationCompleteTon = {
[CT in ConfirmationTypeTon]?: ConfirmationDefinitionsTon[CT][1];
}
export type RequestConfirmationCompleteCardano = {
[CT in ConfirmationTypeCardano]?: ConfirmationDefinitionsCardano[CT][1];
}

export interface BondingOptionParams {
chain: string;
Expand Down Expand Up @@ -2138,8 +2165,10 @@ export interface KoniRequestSignatures {
// Confirmation Queues
'pri(confirmations.subscribe)': [RequestConfirmationsSubscribe, ConfirmationsQueue, ConfirmationsQueue];
'pri(confirmationsTon.subscribe)': [RequestConfirmationsSubscribeTon, ConfirmationsQueueTon, ConfirmationsQueueTon];
'pri(confirmationsCardano.subscribe)': [RequestConfirmationsSubscribeCardano, ConfirmationsQueueCardano, ConfirmationsQueueCardano];
'pri(confirmations.complete)': [RequestConfirmationComplete, boolean];
'pri(confirmationsTon.complete)': [RequestConfirmationCompleteTon, boolean];
'pri(confirmationsCardano.complete)': [RequestConfirmationCompleteCardano, boolean];

'pub(utils.getRandom)': [RandomTestRequest, number];
'pub(accounts.listV2)': [RequestAccountList, InjectedAccount[]];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { _AssetRef, _AssetType, _ChainAsset, _ChainInfo, _MultiChainAsset } from
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
import { createSubscription } from '@subwallet/extension-base/background/handlers/subscriptions';
import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes';
import { AccountExternalError, AddressBookInfo, AmountData, AmountDataWithId, AssetSetting, AssetSettingUpdateReq, BondingOptionParams, BrowserConfirmationType, CampaignBanner, CampaignData, CampaignDataType, ChainType, CronReloadRequest, CrowdloanJson, ExternalRequestPromiseStatus, ExtrinsicType, KeyringState, MantaPayEnableMessage, MantaPayEnableParams, MantaPayEnableResponse, MantaPaySyncState, MetadataItem, NftCollection, NftJson, NftTransactionRequest, NftTransactionResponse, PriceJson, RequestAccountCreateExternalV2, RequestAccountCreateHardwareMultiple, RequestAccountCreateHardwareV2, RequestAccountCreateWithSecretKey, RequestAccountExportPrivateKey, RequestAddInjectedAccounts, RequestApproveConnectWalletSession, RequestApproveWalletConnectNotSupport, RequestAuthorization, RequestAuthorizationBlock, RequestAuthorizationPerAccount, RequestAuthorizationPerSite, RequestAuthorizeApproveV2, RequestBondingSubmit, RequestCameraSettings, RequestCampaignBannerComplete, RequestChangeEnableChainPatrol, RequestChangeLanguage, RequestChangeMasterPassword, RequestChangePriceCurrency, RequestChangeShowBalance, RequestChangeShowZeroBalance, RequestChangeTimeAutoLock, RequestConfirmationComplete, RequestConfirmationCompleteCardano, RequestConfirmationCompleteTon, RequestConnectWalletConnect, RequestCrowdloanContributions, RequestDeleteContactAccount, RequestDisconnectWalletConnectSession, RequestEditContactAccount, RequestFindRawMetadata, RequestForgetSite, RequestFreeBalance, RequestGetTransaction, RequestKeyringExportMnemonic, RequestMaxTransferable, RequestMigratePassword, RequestParseEvmContractInput, RequestParseTransactionSubstrate, RequestPassPhishingPage, RequestQrParseRLP, RequestQrSignEvm, RequestQrSignSubstrate, RequestRejectConnectWalletSession, RequestRejectExternalRequest, RequestRejectWalletConnectNotSupport, RequestRemoveInjectedAccounts, RequestResetWallet, RequestResolveExternalRequest, RequestSaveRecentAccount, RequestSettingsType, RequestSigningApprovePasswordV2, RequestStakePoolingBonding, RequestStakePoolingUnbonding, RequestSubscribeHistory, RequestSubstrateNftSubmitTransaction, RequestTuringCancelStakeCompound, RequestTuringStakeCompound, RequestUnbondingSubmit, RequestUnlockKeyring, RequestUnlockType, ResolveAddressToDomainRequest, ResolveDomainRequest, ResponseAccountCreateWithSecretKey, ResponseAccountExportPrivateKey, ResponseChangeMasterPassword, ResponseFindRawMetadata, ResponseKeyringExportMnemonic, ResponseMigratePassword, ResponseNftImport, ResponseParseEvmContractInput, ResponseParseTransactionSubstrate, ResponseQrParseRLP, ResponseQrSignEvm, ResponseQrSignSubstrate, ResponseRejectExternalRequest, ResponseResetWallet, ResponseResolveExternalRequest, ResponseSubscribeHistory, ResponseUnlockKeyring, ShowCampaignPopupRequest, StakingJson, StakingRewardJson, StakingType, ThemeNames, TransactionHistoryItem, TransactionResponse, ValidateNetworkRequest, ValidateNetworkResponse, ValidatorInfo } from '@subwallet/extension-base/background/KoniTypes';
import { AccountAuthType, AuthorizeRequest, MessageTypes, MetadataRequest, RequestAccountExport, RequestAuthorizeCancel, RequestAuthorizeReject, RequestCurrentAccountAddress, RequestMetadataApprove, RequestMetadataReject, RequestSigningApproveSignature, RequestSigningCancel, RequestTypes, ResponseAccountExport, ResponseAuthorizeList, ResponseType, SigningRequest, WindowOpenParams } from '@subwallet/extension-base/background/types';
import { TransactionWarning } from '@subwallet/extension-base/background/warnings/TransactionWarning';
import { ALL_ACCOUNT_KEY, LATEST_SESSION, XCM_FEE_RATIO } from '@subwallet/extension-base/constants';
Expand Down Expand Up @@ -1937,6 +1937,20 @@ export default class KoniExtension {
return this.#koniState.getConfirmationsQueueSubjectTon().getValue();
}

private subscribeConfirmationsCardano (id: string, port: chrome.runtime.Port) {
const cb = createSubscription<'pri(confirmationsCardano.subscribe)'>(id, port);

const subscription = this.#koniState.getConfirmationsQueueSubjectCardano().subscribe(cb);

this.createUnsubscriptionHandle(id, subscription.unsubscribe);

port.onDisconnect.addListener((): void => {
this.cancelSubscription(id);
});

return this.#koniState.getConfirmationsQueueSubjectCardano().getValue();
}

private async completeConfirmation (request: RequestConfirmationComplete) {
return await this.#koniState.completeConfirmation(request);
}
Expand All @@ -1945,6 +1959,10 @@ export default class KoniExtension {
return await this.#koniState.completeConfirmationTon(request);
}

private async completeConfirmationCardano (request: RequestConfirmationCompleteCardano) {
return await this.#koniState.completeConfirmationCardano(request);
}

/// Sign Qr

private getNetworkJsonByChainId (chainId?: number): _ChainInfo | null {
Expand Down Expand Up @@ -4231,10 +4249,14 @@ export default class KoniExtension {
return this.subscribeConfirmations(id, port);
case 'pri(confirmationsTon.subscribe)':
return this.subscribeConfirmationsTon(id, port);
case 'pri(confirmationsCardano.subscribe)':
return this.subscribeConfirmationsCardano(id, port);
case 'pri(confirmations.complete)':
return await this.completeConfirmation(request as RequestConfirmationComplete);
case 'pri(confirmationsTon.complete)':
return await this.completeConfirmationTon(request as RequestConfirmationCompleteTon);
case 'pri(confirmationsCardano.complete)':
return await this.completeConfirmationCardano(request as RequestConfirmationCompleteCardano);

/// Stake
case 'pri(bonding.getBondingOptions)':
Expand Down
12 changes: 10 additions & 2 deletions packages/extension-base/src/koni/background/handlers/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { EvmProviderError } from '@subwallet/extension-base/background/errors/Ev
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
import { withErrorLog } from '@subwallet/extension-base/background/handlers/helpers';
import { isSubscriptionRunning, unsubscribe } from '@subwallet/extension-base/background/handlers/subscriptions';
import { AddTokenRequestExternal, AmountData, APIItemState, ApiMap, AuthRequestV2, ChainStakingMetadata, ChainType, ConfirmationsQueue, ConfirmationsQueueTon, CrowdloanItem, CrowdloanJson, CurrencyType, EvmProviderErrorType, EvmSendTransactionParams, EvmSendTransactionRequest, EvmSignatureRequest, ExternalRequestPromise, ExternalRequestPromiseStatus, ExtrinsicType, MantaAuthorizationContext, MantaPayConfig, MantaPaySyncState, NftCollection, NftItem, NftJson, NominatorMetadata, RequestAccountExportPrivateKey, RequestConfirmationComplete, RequestConfirmationCompleteTon, RequestCrowdloanContributions, RequestSettingsType, ResponseAccountExportPrivateKey, ServiceInfo, SingleModeJson, StakingItem, StakingJson, StakingRewardItem, StakingRewardJson, StakingType, UiSettings } from '@subwallet/extension-base/background/KoniTypes';
import { AddTokenRequestExternal, AmountData, APIItemState, ApiMap, AuthRequestV2, ChainStakingMetadata, ChainType, ConfirmationsQueue, ConfirmationsQueueCardano, ConfirmationsQueueTon, CrowdloanItem, CrowdloanJson, CurrencyType, EvmProviderErrorType, EvmSendTransactionParams, EvmSendTransactionRequest, EvmSignatureRequest, ExternalRequestPromise, ExternalRequestPromiseStatus, ExtrinsicType, MantaAuthorizationContext, MantaPayConfig, MantaPaySyncState, NftCollection, NftItem, NftJson, NominatorMetadata, RequestAccountExportPrivateKey, RequestConfirmationComplete, RequestConfirmationCompleteCardano, RequestConfirmationCompleteTon, RequestCrowdloanContributions, RequestSettingsType, ResponseAccountExportPrivateKey, ServiceInfo, SingleModeJson, StakingItem, StakingJson, StakingRewardItem, StakingRewardJson, StakingType, UiSettings } from '@subwallet/extension-base/background/KoniTypes';
import { RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestSign, ResponseRpcListProviders, ResponseSigning } from '@subwallet/extension-base/background/types';
import { MANTA_PAY_BALANCE_INTERVAL, REMIND_EXPORT_ACCOUNT } from '@subwallet/extension-base/constants';
import { convertErrorFormat, generateValidationProcess, PayloadValidated, ValidateStepFunction, validationAuthMiddleware, validationAuthWCMiddleware, validationConnectMiddleware, validationEvmDataTransactionMiddleware, validationEvmSignMessageMiddleware } from '@subwallet/extension-base/core/logic-validation';
Expand Down Expand Up @@ -925,7 +925,7 @@ export default class KoniState {
}

public getCardanoApi (networkKey: string) {
return this.chainService.getCardanoApi(networkKey)
return this.chainService.getCardanoApi(networkKey);
}

public getApiMap () {
Expand Down Expand Up @@ -1265,6 +1265,10 @@ export default class KoniState {
return this.requestService.confirmationsQueueSubjectTon;
}

public getConfirmationsQueueSubjectCardano (): BehaviorSubject<ConfirmationsQueueCardano> {
return this.requestService.confirmationsQueueSubjectCardano;
}

public async completeConfirmation (request: RequestConfirmationComplete) {
return await this.requestService.completeConfirmation(request);
}
Expand All @@ -1273,6 +1277,10 @@ export default class KoniState {
return await this.requestService.completeConfirmationTon(request);
}

public async completeConfirmationCardano (request: RequestConfirmationCompleteCardano) {
return await this.requestService.completeConfirmationCardano(request);
}

private async onMV3Update () {
const migrationStatus = await SWStorage.instance.getItem('mv3_migration');

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright 2019-2022 @subwallet/extension-base
// SPDX-License-Identifier: Apache-2.0

import { Transaction } from '@emurgo/cardano-serialization-lib-nodejs';
import { _AssetType, _ChainAsset } from '@subwallet/chain-list/types';
import { _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
import { Transaction } from '@emurgo/cardano-serialization-lib-nodejs';

export function getCardanoAssetId (chainAsset: _ChainAsset): string {
return chainAsset.metadata?.policyId as string;
Expand All @@ -17,6 +17,14 @@ export function _isTokenTransferredByCardano (tokenInfo: _ChainAsset) {
return _isCIP26Token(tokenInfo) || _isNativeToken(tokenInfo);
}

export async function estimateCardanoTxFee (tx: string) {
export function estimateCardanoTxFee (tx: string) {
return Transaction.from_hex(tx).body().fee().to_str();
}

export const cborToBytes = (hex: string): Uint8Array => {
if (hex.length % 2 === 0 && /^[0-9A-F]*$/i.test(hex)) {
return Buffer.from(hex, 'hex');
}

return Buffer.from(hex, 'utf-8');
};
Loading

0 comments on commit 5be20c9

Please sign in to comment.