Skip to content

Commit

Permalink
Merge pull request #1023 from starknet-io/next-version
Browse files Browse the repository at this point in the history
Next version
  • Loading branch information
tabaktoni authored Mar 19, 2024
2 parents 6f87298 + 747f1f7 commit 3d7dc90
Show file tree
Hide file tree
Showing 23 changed files with 1,453 additions and 655 deletions.
8 changes: 8 additions & 0 deletions __tests__/walletAccount.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// TODO Mock: get-starknet UI connect/disconnect wallet
// TODO Create Mock Wallet;

describe('wallet account test', () => {
test('estimateInvokeFee Cairo 0', async () => {
return true;
});
});
864 changes: 248 additions & 616 deletions package-lock.json

Large diffs are not rendered by default.

39 changes: 2 additions & 37 deletions src/account/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,19 @@ import {
import { ETransactionVersion, ETransactionVersion3, ResourceBounds } from '../types/api';
import { CallData } from '../utils/calldata';
import { extractContractHashes, isSierra } from '../utils/contract';
import { starkCurve } from '../utils/ec';
import { parseUDCEvent } from '../utils/events';
import { calculateContractAddressFromHash } from '../utils/hash';
import { toBigInt, toCairoBool } from '../utils/num';
import { parseContract } from '../utils/provider';
import {
estimateFeeToBounds,
formatSignature,
randomAddress,
reduceV2,
toFeeVersion,
toTransactionVersion,
v3Details,
} from '../utils/stark';
import { getExecuteCalldata } from '../utils/transaction';
import { buildUDCCall, getExecuteCalldata } from '../utils/transaction';
import { getMessageHash } from '../utils/typedData';
import { AccountInterface } from './interface';

Expand Down Expand Up @@ -424,40 +422,7 @@ export class Account extends Provider implements AccountInterface {
payload: UniversalDeployerContractPayload | UniversalDeployerContractPayload[],
details: UniversalDetails = {}
): Promise<MultiDeployContractResponse> {
const params = [].concat(payload as []).map((it) => {
const {
classHash,
salt,
unique = true,
constructorCalldata = [],
} = it as UniversalDeployerContractPayload;

const compiledConstructorCallData = CallData.compile(constructorCalldata);
const deploySalt = salt ?? randomAddress();

return {
call: {
contractAddress: UDC.ADDRESS,
entrypoint: UDC.ENTRYPOINT,
calldata: [
classHash,
deploySalt,
toCairoBool(unique),
compiledConstructorCallData.length,
...compiledConstructorCallData,
],
},
address: calculateContractAddressFromHash(
unique ? starkCurve.pedersen(this.address, deploySalt) : deploySalt,
classHash,
compiledConstructorCallData,
unique ? UDC.ADDRESS : 0
),
};
});

const calls = params.map((it) => it.call);
const addresses = params.map((it) => it.address);
const { calls, addresses } = buildUDCCall(payload, this.address);
const invokeResponse = await this.execute(calls, undefined, details);

return {
Expand Down
4 changes: 4 additions & 0 deletions src/channel/rpc_0_6.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export class RpcChannel {
this.requestId = 0;
}

public setChainId(chainId: StarknetChainId) {
this.chainId = chainId;
}

public fetch(method: string, params?: object, id: string | number = 0) {
const rpcRequestBody: JRPC.RequestBody = {
id,
Expand Down
4 changes: 4 additions & 0 deletions src/channel/rpc_0_7.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ export class RpcChannel {
this.requestId = 0;
}

public setChainId(chainId: StarknetChainId) {
this.chainId = chainId;
}

public fetch(method: string, params?: object, id: string | number = 0) {
const rpcRequestBody: JRPC.RequestBody = {
id,
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* Main
*/
export * from './wallet';
export * from './account';
export * from './contract';
export * from './provider';
Expand Down
50 changes: 48 additions & 2 deletions src/utils/transaction.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { UDC } from '../constants';
import {
BigNumberish,
CairoVersion,
Expand All @@ -6,11 +7,14 @@ import {
Calldata,
ParsedStruct,
RawArgs,
UniversalDeployerContractPayload,
} from '../types';
import { ETransactionVersion } from '../types/api';
import { CallData } from './calldata';
import { getSelectorFromName } from './hash';
import { toBigInt } from './num';
import { starkCurve } from './ec';
import { calculateContractAddressFromHash, getSelectorFromName } from './hash';
import { toBigInt, toCairoBool } from './num';
import { randomAddress } from './stark';

/**
* Transforms a list of Calls, each with their own calldata, into
Expand Down Expand Up @@ -94,6 +98,48 @@ export const getExecuteCalldata = (calls: Call[], cairoVersion: CairoVersion = '
return fromCallsToExecuteCalldata(calls);
};

export function buildUDCCall(
payload: UniversalDeployerContractPayload | UniversalDeployerContractPayload[],
address: string
) {
const params = [].concat(payload as []).map((it) => {
const {
classHash,
salt,
unique = true,
constructorCalldata = [],
} = it as UniversalDeployerContractPayload;

const compiledConstructorCallData = CallData.compile(constructorCalldata);
const deploySalt = salt ?? randomAddress();

return {
call: {
contractAddress: UDC.ADDRESS,
entrypoint: UDC.ENTRYPOINT,
calldata: [
classHash,
deploySalt,
toCairoBool(unique),
compiledConstructorCallData.length,
...compiledConstructorCallData,
],
},
address: calculateContractAddressFromHash(
unique ? starkCurve.pedersen(address, deploySalt) : deploySalt,
classHash,
compiledConstructorCallData,
unique ? UDC.ADDRESS : 0
),
};
});

return {
calls: params.map((it) => it.call),
addresses: params.map((it) => it.address),
};
}

/**
* Return transaction versions based on version type, default version type is 'transaction'
*/
Expand Down
188 changes: 188 additions & 0 deletions src/wallet/account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
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();
});

// Update Channel chainId on Network change
this.walletProvider.on('networkChanged', (res) => {
if (!res) return;
// Determine is it better to set chainId or replace channel with new one
// At the moment channel is stateless but it could change
this.channel.setChainId(res as StarknetChainId);
});

// 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);
}

// TODO: MISSING ESTIMATES
}
Loading

0 comments on commit 3d7dc90

Please sign in to comment.