Skip to content

Commit

Permalink
feat: walletAccount extract methods and update new ones
Browse files Browse the repository at this point in the history
  • Loading branch information
tabaktoni committed Mar 18, 2024
1 parent 5e49fc6 commit 0dfb5db
Show file tree
Hide file tree
Showing 18 changed files with 358 additions and 248 deletions.
186 changes: 186 additions & 0 deletions src/wallet/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import { Account, AccountInterface } from '../account';
import { StarknetChainId } from '../constants';
import { ProviderInterface } from '../provider';
import {
AllowArray,
CairoVersion,
Call,
CompiledSierra,
DeclareContractPayload,
DeployAccountContractPayload,
MultiDeployContractResponse,
ProviderOptions,
TypedData,
UniversalDeployerContractPayload,
} from '../types';
import { CallData } from '../utils/calldata';
import { extractContractHashes } from '../utils/contract';
import { stringify } from '../utils/json';
import { buildUDCCall } from '../utils/transaction';
import {
addDeclareTransaction,
addDeployAccountTransaction,
addInvokeTransaction,
addStarknetChain,
getPermissions,
onAccountChange,
onNetworkChanged,
requestAccounts,
signMessage,
switchStarknetChain,
watchAsset,
} from './connect';
import {
AccountChangeEventHandler,
AddStarknetChainParameters,
NetworkChangeEventHandler,
WatchAssetParameters,
} from './getst/main';
import { StarknetWalletProvider } from './types';

// Represent 'Selected Active' Account inside Connected Wallet
export class WalletAccount extends Account implements AccountInterface {
public address: string = '';

public walletProvider: StarknetWalletProvider;

constructor(
providerOrOptions: ProviderOptions | ProviderInterface,
walletProvider: StarknetWalletProvider,
cairoVersion?: CairoVersion
) {
super(providerOrOptions, '', '', cairoVersion); // At this point unknown address
this.walletProvider = walletProvider;

// Update Address on change
this.walletProvider.on('accountsChanged', (res) => {
if (!res) return;
this.address = res[0].toLowerCase();
});

// Throw Error on Network change
this.walletProvider.on('networkChanged', (res) => {
if (!res) return;
throw Error('WalletAccount doest support switching chains');
});

// Get and Set Address !!! Post constructor initial empty string
walletProvider
.request({
type: 'wallet_requestAccounts',
params: {
silentMode: false,
},
})
.then((res) => {
this.address = res[0].toLowerCase();
});
}

/**
* WALLET EVENTS
*/
public onAccountChange(callback: AccountChangeEventHandler) {
onAccountChange(this.walletProvider, callback);
}

public onNetworkChanged(callback: NetworkChangeEventHandler) {
onNetworkChanged(this.walletProvider, callback);
}

/**
* WALLET SPECIFIC METHODS
*/
public requestAccounts(silentMode = false) {
return requestAccounts(this.walletProvider, silentMode);
}

public getPermissions() {
return getPermissions(this.walletProvider);
}

public switchStarknetChain(chainId: StarknetChainId) {
return switchStarknetChain(this.walletProvider, chainId);
}

public watchAsset(asset: WatchAssetParameters) {
return watchAsset(this.walletProvider, asset);
}

public addStarknetChain(chain: AddStarknetChainParameters) {
return addStarknetChain(this.walletProvider, chain);
}

/**
* ACCOUNT METHODS
*/
override execute(calls: AllowArray<Call>) {
const txCalls = [].concat(calls as any).map((it) => {
const { contractAddress, entrypoint, calldata } = it;
return {
contract_address: contractAddress,
entrypoint,
calldata,
};
});

const params = {
calls: txCalls,
};

return addInvokeTransaction(this.walletProvider, params);
}

override declare(payload: DeclareContractPayload) {
const declareContractPayload = extractContractHashes(payload);

// DISCUSS: HOTFIX: Adapt Abi format
const pContract = payload.contract as CompiledSierra;
const cairo1Contract = {
...pContract,
abi: stringify(pContract.abi),
};

// Check FIx
if (!declareContractPayload.compiledClassHash) {
throw Error('compiledClassHash is required');
}

const params = {
compiled_class_hash: declareContractPayload.compiledClassHash,
contract_class: cairo1Contract,
};

return addDeclareTransaction(this.walletProvider, params);
}

override async deploy(
payload: UniversalDeployerContractPayload | UniversalDeployerContractPayload[]
): Promise<MultiDeployContractResponse> {
const { calls, addresses } = buildUDCCall(payload, this.address);
const invokeResponse = await this.execute(calls);

return {
...invokeResponse,
contract_address: addresses,
};
}

override deployAccount(payload: DeployAccountContractPayload) {
const params = {
contract_address_salt: payload.addressSalt?.toString() || '0',
constructor_calldata: payload.constructorCalldata
? CallData.compile(payload.constructorCalldata)
: [],
class_hash: payload.classHash,
};

return addDeployAccountTransaction(this.walletProvider, params);
}

override signMessage(typedData: TypedData) {
return signMessage(this.walletProvider, typedData);
}

// MISSING ESTIMATES
}
162 changes: 162 additions & 0 deletions src/wallet/connect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import {
AccountChangeEventHandler,
AddDeclareTransactionParameters,
AddDeployAccountTransactionParameters,
AddInvokeTransactionParameters,
AddStarknetChainParameters,
NetworkChangeEventHandler,
StarknetChainId,
StarknetWindowObject,
TypedData,
WatchAssetParameters,
} from './getst/main';

/**
* Request Permission for wallet account, return addresses that's allowed by user
* @param silentMode false: request user interaction allowance. true: return only pre-allowed
* @returns allowed accounts addresses
*/
export function requestAccounts(swo: StarknetWindowObject, silentMode = false) {
return swo.request({
type: 'wallet_requestAccounts',
params: {
silentMode,
},
});
}

/**
* Request Permission for wallet account
* @returns allowed accounts addresses
*/
export function getPermissions(swo: StarknetWindowObject) {
return swo.request({ type: 'wallet_getPermissions' });
}

/**
* Request adding ERC20 Token to Wallet List
* @param asset WatchAssetParameters
* @returns boolean
*/
export function watchAsset(swo: StarknetWindowObject, asset: WatchAssetParameters) {
return swo.request({
type: 'wallet_watchAsset',
params: asset,
});
}

/**
* Request adding custom Starknet chain
* @param chain AddStarknetChainParameters
* @returns boolean
*/
export function addStarknetChain(swo: StarknetWindowObject, chain: AddStarknetChainParameters) {
// Can this set custom RPC endpoint ?
return swo.request({
type: 'wallet_addStarknetChain',
params: chain,
});
}

/**
* Request Wallet Network change
* @param chainId StarknetChainId
* @returns boolean
*/
export function switchStarknetChain(swo: StarknetWindowObject, chainId: StarknetChainId) {
return swo.request({
type: 'wallet_switchStarknetChain',
params: {
chainId,
},
});
}

/**
* Request the current chain ID from the wallet.
* @returns The current Starknet chain ID.
*/
export function requestChainId(swo: StarknetWindowObject) {
return swo.request({ type: 'wallet_requestChainId' });
}

/**
* Get deployment data for a contract.
* @returns The deployment data result.
*/
export function deploymentData(swo: StarknetWindowObject) {
return swo.request({ type: 'wallet_deploymentData' }); // TODO: test
}

/**
* Add an invoke transaction to the wallet.
* @param params The parameters required for the invoke transaction.
* @returns The result of adding the invoke transaction.
*/
export function addInvokeTransaction(
swo: StarknetWindowObject,
params: AddInvokeTransactionParameters
) {
return swo.request({
type: 'starknet_addInvokeTransaction',
params,
});
}

/**
* Add a declare transaction to the wallet.
* @param params The parameters required for the declare transaction.
* @returns The result of adding the declare transaction.
*/
export function addDeclareTransaction(
swo: StarknetWindowObject,
params: AddDeclareTransactionParameters
) {
return swo.request({
type: 'starknet_addDeclareTransaction',
params,
});
}

/**
* Add a deploy account transaction to the wallet.
* @param params The parameters required for the deploy account transaction.
* @returns The result of adding the deploy account transaction.
*/
export function addDeployAccountTransaction(
swo: StarknetWindowObject,
params: AddDeployAccountTransactionParameters
) {
return swo.request({
type: 'starknet_addDeployAccountTransaction',
params,
});
}

/**
* Sign typed data using the wallet.
* @param params The typed data to sign.
* @returns An array of signatures as strings.
*/
export function signMessage(swo: StarknetWindowObject, typedData: TypedData) {
return swo.request({
type: 'starknet_signTypedData',
params: typedData,
});
}

/**
* Get the list of supported specifications.
* @returns An array of supported specification strings.
*/
export function supportedSpecs(swo: StarknetWindowObject) {
return swo.request({ type: 'starknet_supportedSpecs' });
}

export function onAccountChange(swo: StarknetWindowObject, callback: AccountChangeEventHandler) {
swo.on('accountsChanged', callback);
}

export function onNetworkChanged(swo: StarknetWindowObject, callback: NetworkChangeEventHandler) {
swo.on('networkChanged', callback);
}
Loading

0 comments on commit 0dfb5db

Please sign in to comment.