@cartridge/controller 0.10.0-alpha.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build$colon$deps.log +18 -18
- package/.turbo/turbo-build.log +17 -17
- package/dist/index.js +2385 -1100
- package/dist/index.js.map +1 -1
- package/dist/node/index.cjs +1 -1
- package/dist/node/index.cjs.map +1 -1
- package/dist/node/index.js +1 -1
- package/dist/node/index.js.map +1 -1
- package/dist/{provider-CKE81veU.js → provider-Bsw_spHR.js} +2 -2
- package/dist/{provider-CKE81veU.js.map → provider-Bsw_spHR.js.map} +1 -1
- package/dist/session.js +3 -3
- package/dist/session.js.map +1 -1
- package/dist/stats.html +1 -1
- package/dist/utils/solana/connection.d.ts +19 -0
- package/dist/utils/solana/index.d.ts +37 -0
- package/dist/utils/solana/spl-token.d.ts +6 -0
- package/dist/wallets/base/index.d.ts +5 -18
- package/dist/wallets/ethereum-base.d.ts +29 -0
- package/dist/wallets/index.d.ts +2 -0
- package/dist/wallets/metamask/index.d.ts +5 -19
- package/dist/wallets/rabby/index.d.ts +5 -19
- package/package.json +5 -7
- package/src/__tests__/controllerDefaults.test.ts +5 -5
- package/src/__tests__/parseChainId.test.ts +6 -2
- package/src/controller.ts +3 -3
- package/src/utils/solana/connection.ts +78 -0
- package/src/utils/solana/index.ts +143 -0
- package/src/utils/solana/spl-token.ts +66 -0
- package/src/wallets/base/index.ts +5 -303
- package/src/wallets/ethereum-base.ts +446 -0
- package/src/wallets/index.ts +2 -0
- package/src/wallets/metamask/index.ts +5 -334
- package/src/wallets/phantom/index.ts +5 -1
- package/src/wallets/rabby/index.ts +5 -332
- package/vite.config.js +0 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface ConnectionConfig {
|
|
2
|
+
commitment?: "processed" | "confirmed" | "finalized";
|
|
3
|
+
}
|
|
4
|
+
export declare class Connection {
|
|
5
|
+
private rpcUrl;
|
|
6
|
+
private commitment;
|
|
7
|
+
constructor(rpcUrl: string, config?: ConnectionConfig);
|
|
8
|
+
private rpcRequest;
|
|
9
|
+
getLatestBlockhash(): Promise<{
|
|
10
|
+
blockhash: any;
|
|
11
|
+
lastValidBlockHeight: any;
|
|
12
|
+
}>;
|
|
13
|
+
getSignatureStatus(signature: string): Promise<any>;
|
|
14
|
+
sendRawTransaction(transaction: Uint8Array, options?: {
|
|
15
|
+
skipPreflight?: boolean;
|
|
16
|
+
maxRetries?: number;
|
|
17
|
+
}): Promise<any>;
|
|
18
|
+
getAccountInfo(publicKey: string): Promise<any>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import * as sol from "micro-sol-signer";
|
|
2
|
+
export * from 'micro-sol-signer';
|
|
3
|
+
export { Connection } from './connection';
|
|
4
|
+
export * from './spl-token';
|
|
5
|
+
export declare class PublicKey {
|
|
6
|
+
private _publicKey;
|
|
7
|
+
constructor(value: string | Uint8Array | number[] | Buffer | PublicKey);
|
|
8
|
+
toString(): string;
|
|
9
|
+
toBytes(): Uint8Array;
|
|
10
|
+
toBuffer(): Buffer;
|
|
11
|
+
equals(other: PublicKey | string): boolean;
|
|
12
|
+
toBase58(): string;
|
|
13
|
+
}
|
|
14
|
+
export declare class Transaction {
|
|
15
|
+
private _transaction;
|
|
16
|
+
signatures: Array<{
|
|
17
|
+
signature: Uint8Array | null;
|
|
18
|
+
publicKey: PublicKey;
|
|
19
|
+
}>;
|
|
20
|
+
feePayer?: PublicKey;
|
|
21
|
+
recentBlockhash?: string;
|
|
22
|
+
private _instructions;
|
|
23
|
+
constructor();
|
|
24
|
+
add(...instructions: sol.Instruction[]): Transaction;
|
|
25
|
+
static from(buffer: Uint8Array | Buffer | number[]): Transaction;
|
|
26
|
+
serialize(_options?: {
|
|
27
|
+
requireAllSignatures?: boolean;
|
|
28
|
+
}): Buffer;
|
|
29
|
+
serializeMessage(): Buffer;
|
|
30
|
+
}
|
|
31
|
+
export declare class VersionedTransaction {
|
|
32
|
+
message: any;
|
|
33
|
+
signatures: Uint8Array[];
|
|
34
|
+
constructor(message: any, signatures: Uint8Array[]);
|
|
35
|
+
static deserialize(serialized: Uint8Array): VersionedTransaction;
|
|
36
|
+
serialize(): Uint8Array;
|
|
37
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import * as sol from "micro-sol-signer";
|
|
2
|
+
export declare const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
3
|
+
export declare const ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
|
|
4
|
+
export declare function getAssociatedTokenAddress(mint: string, owner: string): string;
|
|
5
|
+
export declare function createAssociatedTokenAccountInstruction(payer: string, associatedToken: string, owner: string, mint: string): sol.Instruction;
|
|
6
|
+
export declare function createTransferInstruction(source: string, destination: string, owner: string, amount: bigint): sol.Instruction;
|
|
@@ -1,20 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ExternalWalletType } from '../types';
|
|
2
|
+
import { EthereumWalletBase } from '../ethereum-base';
|
|
3
|
+
export declare class BaseWallet extends EthereumWalletBase {
|
|
3
4
|
readonly type: ExternalWalletType;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
private store;
|
|
7
|
-
private provider;
|
|
8
|
-
private connectedAccounts;
|
|
9
|
-
constructor();
|
|
10
|
-
isAvailable(): boolean;
|
|
11
|
-
getInfo(): ExternalWallet;
|
|
12
|
-
getConnectedAccounts(): string[];
|
|
13
|
-
connect(address?: string): Promise<ExternalWalletResponse<any>>;
|
|
14
|
-
signMessage(message: `0x${string}`, address?: string): Promise<ExternalWalletResponse<any>>;
|
|
15
|
-
signTypedData(data: any): Promise<ExternalWalletResponse<any>>;
|
|
16
|
-
sendTransaction(txn: any): Promise<ExternalWalletResponse<any>>;
|
|
17
|
-
switchChain(chainId: string): Promise<boolean>;
|
|
18
|
-
getBalance(tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
|
|
19
|
-
waitForTransaction(txHash: string, timeoutMs?: number): Promise<ExternalWalletResponse<any>>;
|
|
5
|
+
readonly rdns = "com.coinbase.wallet";
|
|
6
|
+
readonly displayName = "Base Wallet";
|
|
20
7
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { EIP6963ProviderDetail } from 'mipd';
|
|
2
|
+
import { ExternalPlatform, ExternalWallet, ExternalWalletResponse, ExternalWalletType, WalletAdapter } from './types';
|
|
3
|
+
export declare abstract class EthereumWalletBase implements WalletAdapter {
|
|
4
|
+
abstract readonly type: ExternalWalletType;
|
|
5
|
+
abstract readonly rdns: string;
|
|
6
|
+
abstract readonly displayName: string;
|
|
7
|
+
platform: ExternalPlatform | undefined;
|
|
8
|
+
protected account: string | undefined;
|
|
9
|
+
protected store: import('mipd').Store;
|
|
10
|
+
protected provider: EIP6963ProviderDetail | undefined;
|
|
11
|
+
protected connectedAccounts: string[];
|
|
12
|
+
constructor();
|
|
13
|
+
private getProvider;
|
|
14
|
+
private getEthereumProvider;
|
|
15
|
+
private initializeIfAvailable;
|
|
16
|
+
private initialized;
|
|
17
|
+
private initializeProvider;
|
|
18
|
+
isAvailable(): boolean;
|
|
19
|
+
getInfo(): ExternalWallet;
|
|
20
|
+
getConnectedAccounts(): string[];
|
|
21
|
+
connect(address?: string): Promise<ExternalWalletResponse<any>>;
|
|
22
|
+
signTransaction(transaction: any): Promise<ExternalWalletResponse<any>>;
|
|
23
|
+
signMessage(message: string | `0x${string}`, address?: string): Promise<ExternalWalletResponse<any>>;
|
|
24
|
+
signTypedData(data: any): Promise<ExternalWalletResponse<any>>;
|
|
25
|
+
sendTransaction(txn: any): Promise<ExternalWalletResponse<any>>;
|
|
26
|
+
switchChain(chainId: string): Promise<boolean>;
|
|
27
|
+
getBalance(tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
|
|
28
|
+
waitForTransaction(txHash: string, timeoutMs?: number): Promise<ExternalWalletResponse<any>>;
|
|
29
|
+
}
|
package/dist/wallets/index.d.ts
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ExternalWalletType } from '../types';
|
|
2
|
+
import { EthereumWalletBase } from '../ethereum-base';
|
|
3
|
+
export declare class MetaMaskWallet extends EthereumWalletBase {
|
|
3
4
|
readonly type: ExternalWalletType;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
private store;
|
|
7
|
-
private account;
|
|
8
|
-
private connectedAccounts;
|
|
9
|
-
constructor();
|
|
10
|
-
isAvailable(): boolean;
|
|
11
|
-
getInfo(): ExternalWallet;
|
|
12
|
-
connect(): Promise<ExternalWalletResponse<any>>;
|
|
13
|
-
getConnectedAccounts(): string[];
|
|
14
|
-
signTransaction(transaction: any): Promise<ExternalWalletResponse<any>>;
|
|
15
|
-
signMessage(message: string, address?: string): Promise<ExternalWalletResponse<any>>;
|
|
16
|
-
signTypedData(data: any): Promise<ExternalWalletResponse<any>>;
|
|
17
|
-
sendTransaction(txn: any): Promise<ExternalWalletResponse<any>>;
|
|
18
|
-
switchChain(chainId: string): Promise<boolean>;
|
|
19
|
-
getBalance(tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
|
|
20
|
-
waitForTransaction(txHash: string, timeoutMs?: number): Promise<ExternalWalletResponse<any>>;
|
|
5
|
+
readonly rdns = "io.metamask";
|
|
6
|
+
readonly displayName = "MetaMask";
|
|
21
7
|
}
|
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ExternalWalletType } from '../types';
|
|
2
|
+
import { EthereumWalletBase } from '../ethereum-base';
|
|
3
|
+
export declare class RabbyWallet extends EthereumWalletBase {
|
|
3
4
|
readonly type: ExternalWalletType;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
private store;
|
|
7
|
-
private provider;
|
|
8
|
-
private connectedAccounts;
|
|
9
|
-
constructor();
|
|
10
|
-
isAvailable(): boolean;
|
|
11
|
-
getInfo(): ExternalWallet;
|
|
12
|
-
connect(address?: string): Promise<ExternalWalletResponse<any>>;
|
|
13
|
-
getConnectedAccounts(): string[];
|
|
14
|
-
signTransaction(transaction: any): Promise<ExternalWalletResponse<any>>;
|
|
15
|
-
signMessage(message: `0x${string}`, address?: string): Promise<ExternalWalletResponse<any>>;
|
|
16
|
-
signTypedData(data: any): Promise<ExternalWalletResponse<any>>;
|
|
17
|
-
sendTransaction(txn: any): Promise<ExternalWalletResponse<any>>;
|
|
18
|
-
switchChain(chainId: string): Promise<boolean>;
|
|
19
|
-
getBalance(tokenAddress?: string): Promise<ExternalWalletResponse<any>>;
|
|
20
|
-
waitForTransaction(txHash: string, timeoutMs?: number): Promise<ExternalWalletResponse<any>>;
|
|
5
|
+
readonly rdns = "io.rabby";
|
|
6
|
+
readonly displayName = "Rabby";
|
|
21
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cartridge/controller",
|
|
3
|
-
"version": "0.10.0
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Cartridge Controller",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -20,13 +20,11 @@
|
|
|
20
20
|
"require": "./dist/node/index.cjs"
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
|
-
"peerDependencies": {
|
|
24
|
-
"@metamask/sdk": "^0.32.1",
|
|
25
|
-
"@solana/web3.js": "^1.98.0"
|
|
26
|
-
},
|
|
27
23
|
"dependencies": {
|
|
28
|
-
"@cartridge/controller-wasm": "^0.
|
|
24
|
+
"@cartridge/controller-wasm": "^0.3.3",
|
|
29
25
|
"@cartridge/penpal": "^6.2.4",
|
|
26
|
+
"micro-sol-signer": "^0.5.0",
|
|
27
|
+
"bs58": "^6.0.0",
|
|
30
28
|
"ethers": "^6.13.5",
|
|
31
29
|
"@starknet-io/types-js": "0.9.1",
|
|
32
30
|
"@telegram-apps/sdk": "^2.4.0",
|
|
@@ -52,7 +50,7 @@
|
|
|
52
50
|
"vite-plugin-node-polyfills": "^0.23.0",
|
|
53
51
|
"vite-plugin-top-level-await": "^1.4.4",
|
|
54
52
|
"vite-plugin-wasm": "^3.4.1",
|
|
55
|
-
"@cartridge/tsconfig": "0.10.0
|
|
53
|
+
"@cartridge/tsconfig": "0.10.0"
|
|
56
54
|
},
|
|
57
55
|
"scripts": {
|
|
58
56
|
"build:deps": "pnpm build",
|
|
@@ -22,13 +22,13 @@ describe("ControllerProvider defaults", () => {
|
|
|
22
22
|
const controller = new ControllerProvider({});
|
|
23
23
|
|
|
24
24
|
expect(controller.rpcUrl()).toBe(
|
|
25
|
-
"https://api.cartridge.gg/x/starknet/mainnet",
|
|
25
|
+
"https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_9",
|
|
26
26
|
);
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
test("should use custom chains when provided", () => {
|
|
30
30
|
const customChains = [
|
|
31
|
-
{ rpcUrl: "https://api.cartridge.gg/x/starknet/sepolia" },
|
|
31
|
+
{ rpcUrl: "https://api.cartridge.gg/x/starknet/sepolia/rpc/v0_9" },
|
|
32
32
|
];
|
|
33
33
|
|
|
34
34
|
const controller = new ControllerProvider({
|
|
@@ -37,13 +37,13 @@ describe("ControllerProvider defaults", () => {
|
|
|
37
37
|
});
|
|
38
38
|
|
|
39
39
|
expect(controller.rpcUrl()).toBe(
|
|
40
|
-
"https://api.cartridge.gg/x/starknet/sepolia",
|
|
40
|
+
"https://api.cartridge.gg/x/starknet/sepolia/rpc/v0_9",
|
|
41
41
|
);
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
test("should throw error when using non-Cartridge RPC for mainnet", async () => {
|
|
45
45
|
const invalidChains = [
|
|
46
|
-
{ rpcUrl: "https://some-other-provider.com/starknet/mainnet" },
|
|
46
|
+
{ rpcUrl: "https://some-other-provider.com/starknet/mainnet/rpc/v0_9" },
|
|
47
47
|
];
|
|
48
48
|
|
|
49
49
|
expect(() => {
|
|
@@ -56,7 +56,7 @@ describe("ControllerProvider defaults", () => {
|
|
|
56
56
|
|
|
57
57
|
test("should throw error when using non-Cartridge RPC for sepolia", async () => {
|
|
58
58
|
const invalidChains = [
|
|
59
|
-
{ rpcUrl: "https://some-other-provider.com/starknet/sepolia" },
|
|
59
|
+
{ rpcUrl: "https://some-other-provider.com/starknet/sepolia/rpc/v0_9" },
|
|
60
60
|
];
|
|
61
61
|
|
|
62
62
|
expect(() => {
|
|
@@ -5,13 +5,17 @@ describe("parseChainId", () => {
|
|
|
5
5
|
describe("Starknet chains", () => {
|
|
6
6
|
test("identifies mainnet", () => {
|
|
7
7
|
expect(
|
|
8
|
-
parseChainId(
|
|
8
|
+
parseChainId(
|
|
9
|
+
new URL("https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_9"),
|
|
10
|
+
),
|
|
9
11
|
).toBe(constants.StarknetChainId.SN_MAIN);
|
|
10
12
|
});
|
|
11
13
|
|
|
12
14
|
test("identifies sepolia", () => {
|
|
13
15
|
expect(
|
|
14
|
-
parseChainId(
|
|
16
|
+
parseChainId(
|
|
17
|
+
new URL("https://api.cartridge.gg/x/starknet/sepolia/rpc/v0_9"),
|
|
18
|
+
),
|
|
15
19
|
).toBe(constants.StarknetChainId.SN_SEPOLIA);
|
|
16
20
|
});
|
|
17
21
|
});
|
package/src/controller.ts
CHANGED
|
@@ -41,8 +41,8 @@ export default class ControllerProvider extends BaseProvider {
|
|
|
41
41
|
|
|
42
42
|
// Default Cartridge chains that are always available
|
|
43
43
|
const cartridgeChains: Chain[] = [
|
|
44
|
-
{ rpcUrl: "https://api.cartridge.gg/x/starknet/sepolia" },
|
|
45
|
-
{ rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet" },
|
|
44
|
+
{ rpcUrl: "https://api.cartridge.gg/x/starknet/sepolia/rpc/v0_9" },
|
|
45
|
+
{ rpcUrl: "https://api.cartridge.gg/x/starknet/mainnet/rpc/v0_9" },
|
|
46
46
|
];
|
|
47
47
|
|
|
48
48
|
// Merge user chains with default chains
|
|
@@ -425,7 +425,7 @@ export default class ControllerProvider extends BaseProvider {
|
|
|
425
425
|
if ((isMainnet || isSepolia) && !(isCartridgeRpc || isLocalhost)) {
|
|
426
426
|
throw new Error(
|
|
427
427
|
`Only Cartridge RPC providers are allowed for ${isMainnet ? "mainnet" : "sepolia"}. ` +
|
|
428
|
-
`Please use: https://api.cartridge.gg/x/starknet/${isMainnet ? "mainnet" : "sepolia"}`,
|
|
428
|
+
`Please use: https://api.cartridge.gg/x/starknet/${isMainnet ? "mainnet" : "sepolia"}/rpc/v0_9`,
|
|
429
429
|
);
|
|
430
430
|
}
|
|
431
431
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import bs58 from "bs58";
|
|
2
|
+
|
|
3
|
+
export interface ConnectionConfig {
|
|
4
|
+
commitment?: "processed" | "confirmed" | "finalized";
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class Connection {
|
|
8
|
+
private rpcUrl: string;
|
|
9
|
+
private commitment: string;
|
|
10
|
+
|
|
11
|
+
constructor(rpcUrl: string, config?: ConnectionConfig) {
|
|
12
|
+
this.rpcUrl = rpcUrl;
|
|
13
|
+
this.commitment = config?.commitment || "confirmed";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private async rpcRequest(method: string, params: any[] = []) {
|
|
17
|
+
const response = await fetch(this.rpcUrl, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: {
|
|
20
|
+
"Content-Type": "application/json",
|
|
21
|
+
},
|
|
22
|
+
body: JSON.stringify({
|
|
23
|
+
jsonrpc: "2.0",
|
|
24
|
+
id: 1,
|
|
25
|
+
method,
|
|
26
|
+
params,
|
|
27
|
+
}),
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const json = await response.json();
|
|
31
|
+
if (json.error) {
|
|
32
|
+
throw new Error(`RPC Error: ${json.error.message}`);
|
|
33
|
+
}
|
|
34
|
+
return json.result;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async getLatestBlockhash() {
|
|
38
|
+
const result = await this.rpcRequest("getLatestBlockhash", [
|
|
39
|
+
{ commitment: this.commitment },
|
|
40
|
+
]);
|
|
41
|
+
return {
|
|
42
|
+
blockhash: result.value.blockhash,
|
|
43
|
+
lastValidBlockHeight: result.value.lastValidBlockHeight,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async getSignatureStatus(signature: string) {
|
|
48
|
+
const result = await this.rpcRequest("getSignatureStatuses", [
|
|
49
|
+
[signature],
|
|
50
|
+
{ searchTransactionHistory: true },
|
|
51
|
+
]);
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async sendRawTransaction(
|
|
56
|
+
transaction: Uint8Array,
|
|
57
|
+
options?: { skipPreflight?: boolean; maxRetries?: number },
|
|
58
|
+
) {
|
|
59
|
+
const encoded = bs58.encode(transaction);
|
|
60
|
+
const result = await this.rpcRequest("sendTransaction", [
|
|
61
|
+
encoded,
|
|
62
|
+
{
|
|
63
|
+
encoding: "base58",
|
|
64
|
+
skipPreflight: options?.skipPreflight || false,
|
|
65
|
+
maxRetries: options?.maxRetries,
|
|
66
|
+
},
|
|
67
|
+
]);
|
|
68
|
+
return result;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async getAccountInfo(publicKey: string) {
|
|
72
|
+
const result = await this.rpcRequest("getAccountInfo", [
|
|
73
|
+
publicKey,
|
|
74
|
+
{ encoding: "base64", commitment: this.commitment },
|
|
75
|
+
]);
|
|
76
|
+
return result;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import * as sol from "micro-sol-signer";
|
|
2
|
+
import bs58 from "bs58";
|
|
3
|
+
|
|
4
|
+
// Re-export from micro-sol-signer
|
|
5
|
+
export * from "micro-sol-signer";
|
|
6
|
+
|
|
7
|
+
// Export our custom utilities
|
|
8
|
+
export { Connection } from "./connection";
|
|
9
|
+
export * from "./spl-token";
|
|
10
|
+
|
|
11
|
+
// Additional compatibility layer for easier migration
|
|
12
|
+
export class PublicKey {
|
|
13
|
+
private _publicKey: string;
|
|
14
|
+
|
|
15
|
+
constructor(value: string | Uint8Array | number[] | Buffer | PublicKey) {
|
|
16
|
+
if (value instanceof PublicKey) {
|
|
17
|
+
this._publicKey = value.toString();
|
|
18
|
+
} else if (typeof value === "string") {
|
|
19
|
+
this._publicKey = value;
|
|
20
|
+
} else if (
|
|
21
|
+
value instanceof Uint8Array ||
|
|
22
|
+
Array.isArray(value) ||
|
|
23
|
+
Buffer.isBuffer(value)
|
|
24
|
+
) {
|
|
25
|
+
const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
26
|
+
this._publicKey = bs58.encode(bytes);
|
|
27
|
+
} else {
|
|
28
|
+
throw new Error("Invalid public key input");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
toString(): string {
|
|
33
|
+
return this._publicKey;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
toBytes(): Uint8Array {
|
|
37
|
+
return bs58.decode(this._publicKey);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
toBuffer(): Buffer {
|
|
41
|
+
return Buffer.from(this.toBytes());
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
equals(other: PublicKey | string): boolean {
|
|
45
|
+
const otherKey = other instanceof PublicKey ? other.toString() : other;
|
|
46
|
+
return this._publicKey === otherKey;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
toBase58(): string {
|
|
50
|
+
return this._publicKey;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Transaction compatibility wrapper
|
|
55
|
+
export class Transaction {
|
|
56
|
+
private _transaction: any;
|
|
57
|
+
public signatures: Array<{
|
|
58
|
+
signature: Uint8Array | null;
|
|
59
|
+
publicKey: PublicKey;
|
|
60
|
+
}> = [];
|
|
61
|
+
public feePayer?: PublicKey;
|
|
62
|
+
public recentBlockhash?: string;
|
|
63
|
+
private _instructions: sol.Instruction[];
|
|
64
|
+
|
|
65
|
+
constructor() {
|
|
66
|
+
// We'll build instructions array and serialize using micro-sol-signer
|
|
67
|
+
this._instructions = [];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
add(...instructions: sol.Instruction[]): Transaction {
|
|
71
|
+
this._instructions.push(...instructions);
|
|
72
|
+
return this;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static from(buffer: Uint8Array | Buffer | number[]): Transaction {
|
|
76
|
+
// Decode using micro-sol-signer
|
|
77
|
+
const bytes =
|
|
78
|
+
buffer instanceof Uint8Array ? buffer : new Uint8Array(buffer);
|
|
79
|
+
const decoded = sol.Transaction.decode(bytes);
|
|
80
|
+
|
|
81
|
+
// Create a new Transaction and populate it
|
|
82
|
+
const tx = new Transaction();
|
|
83
|
+
// Note: This would need proper mapping from decoded to our wrapper
|
|
84
|
+
// For now, storing the raw decoded transaction
|
|
85
|
+
tx._transaction = decoded;
|
|
86
|
+
return tx;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
serialize(_options?: { requireAllSignatures?: boolean }): Buffer {
|
|
90
|
+
// Build transaction using micro-sol-signer
|
|
91
|
+
if (this._transaction) {
|
|
92
|
+
// If we have a decoded transaction, re-serialize it
|
|
93
|
+
return Buffer.from(sol.Transaction.encode(this._transaction));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Build from instructions
|
|
97
|
+
if (!this.feePayer || !this.recentBlockhash) {
|
|
98
|
+
throw new Error("Transaction requires feePayer and recentBlockhash");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const txHex = sol.createTxComplex(
|
|
102
|
+
this.feePayer.toString(),
|
|
103
|
+
this._instructions,
|
|
104
|
+
this.recentBlockhash,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
return Buffer.from(txHex, "hex");
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
serializeMessage(): Buffer {
|
|
111
|
+
// Serialize just the message part
|
|
112
|
+
if (!this.feePayer || !this.recentBlockhash) {
|
|
113
|
+
throw new Error("Transaction requires feePayer and recentBlockhash");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const txHex = sol.createTxComplex(
|
|
117
|
+
this.feePayer.toString(),
|
|
118
|
+
this._instructions,
|
|
119
|
+
this.recentBlockhash,
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// Return the message part of the transaction
|
|
123
|
+
return Buffer.from(txHex, "hex");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Versioned transaction support
|
|
128
|
+
export class VersionedTransaction {
|
|
129
|
+
constructor(
|
|
130
|
+
public message: any,
|
|
131
|
+
public signatures: Uint8Array[],
|
|
132
|
+
) {}
|
|
133
|
+
|
|
134
|
+
static deserialize(serialized: Uint8Array): VersionedTransaction {
|
|
135
|
+
const decoded = sol.Transaction.decode(serialized);
|
|
136
|
+
// Map to VersionedTransaction format
|
|
137
|
+
return new VersionedTransaction(decoded, []);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
serialize(): Uint8Array {
|
|
141
|
+
return sol.Transaction.encode(this.message);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as sol from "micro-sol-signer";
|
|
2
|
+
import bs58 from "bs58";
|
|
3
|
+
|
|
4
|
+
// SPL Token Program IDs
|
|
5
|
+
export const TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
6
|
+
export const ASSOCIATED_TOKEN_PROGRAM_ID =
|
|
7
|
+
"ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
|
|
8
|
+
|
|
9
|
+
// Helper to get associated token address
|
|
10
|
+
export function getAssociatedTokenAddress(mint: string, owner: string): string {
|
|
11
|
+
// Derive the associated token account address
|
|
12
|
+
// This is a simplified implementation for compatibility
|
|
13
|
+
const seeds = [
|
|
14
|
+
bs58.decode(owner),
|
|
15
|
+
bs58.decode(TOKEN_PROGRAM_ID),
|
|
16
|
+
bs58.decode(mint),
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
// For SPL Token ATAs, this is deterministic but simplified
|
|
20
|
+
// In production, use proper PDA derivation
|
|
21
|
+
const combined = Buffer.concat(seeds.map((s) => Buffer.from(s)));
|
|
22
|
+
const hash = Buffer.from(combined).slice(0, 32);
|
|
23
|
+
return bs58.encode(hash);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Create associated token account instruction
|
|
27
|
+
export function createAssociatedTokenAccountInstruction(
|
|
28
|
+
payer: string,
|
|
29
|
+
associatedToken: string,
|
|
30
|
+
owner: string,
|
|
31
|
+
mint: string,
|
|
32
|
+
): sol.Instruction {
|
|
33
|
+
// Create the instruction to create an associated token account
|
|
34
|
+
return {
|
|
35
|
+
program: ASSOCIATED_TOKEN_PROGRAM_ID,
|
|
36
|
+
keys: [
|
|
37
|
+
{ address: payer, sign: true, write: true },
|
|
38
|
+
{ address: associatedToken, sign: false, write: true },
|
|
39
|
+
{ address: owner, sign: false, write: false },
|
|
40
|
+
{ address: mint, sign: false, write: false },
|
|
41
|
+
{
|
|
42
|
+
address: "11111111111111111111111111111111",
|
|
43
|
+
sign: false,
|
|
44
|
+
write: false,
|
|
45
|
+
}, // System program
|
|
46
|
+
{ address: TOKEN_PROGRAM_ID, sign: false, write: false },
|
|
47
|
+
],
|
|
48
|
+
data: new Uint8Array(0), // No data for create instruction
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Create transfer instruction
|
|
53
|
+
export function createTransferInstruction(
|
|
54
|
+
source: string,
|
|
55
|
+
destination: string,
|
|
56
|
+
owner: string,
|
|
57
|
+
amount: bigint,
|
|
58
|
+
): sol.Instruction {
|
|
59
|
+
// Use micro-sol-signer's token transfer instruction
|
|
60
|
+
return sol.token.transfer({
|
|
61
|
+
source,
|
|
62
|
+
destination,
|
|
63
|
+
owner,
|
|
64
|
+
amount,
|
|
65
|
+
});
|
|
66
|
+
}
|