@wireio/stake 0.0.6 → 0.1.1
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/README.md +260 -13
- package/lib/stake.browser.js +4861 -4218
- package/lib/stake.browser.js.map +1 -1
- package/lib/stake.d.ts +434 -6484
- package/lib/stake.js +5059 -4371
- package/lib/stake.js.map +1 -1
- package/lib/stake.m.js +4861 -4218
- package/lib/stake.m.js.map +1 -1
- package/package.json +2 -2
- package/src/assets/solana/idl/liqsol_core.json +4239 -0
- package/src/assets/solana/idl/liqsol_token.json +183 -0
- package/src/assets/solana/idl/validator_leaderboard.json +296 -250
- package/src/assets/solana/types/liqsol_core.ts +4245 -0
- package/src/assets/solana/types/liqsol_token.ts +189 -0
- package/src/assets/solana/types/validator_leaderboard.ts +296 -250
- package/src/index.ts +2 -5
- package/src/networks/ethereum/contract.ts +138 -36
- package/src/networks/ethereum/ethereum.ts +167 -38
- package/src/networks/ethereum/types.ts +32 -1
- package/src/networks/solana/clients/deposit.client.ts +92 -139
- package/src/networks/solana/clients/distribution.client.ts +302 -178
- package/src/networks/solana/clients/leaderboard.client.ts +40 -160
- package/src/networks/solana/constants.ts +238 -69
- package/src/networks/solana/program.ts +27 -93
- package/src/networks/solana/solana.ts +181 -36
- package/src/networks/solana/types.ts +47 -0
- package/src/networks/solana/utils.ts +522 -93
- package/src/scripts/fetch-artifacts.sh +24 -0
- package/src/scripts/tsconfig.json +17 -0
- package/src/staker/staker.ts +35 -30
- package/src/staker/types.ts +25 -22
- package/src/assets/solana/idl/deposit.json +0 -260
- package/src/assets/solana/idl/distribution.json +0 -736
- package/src/assets/solana/idl/liq_sol_token.json +0 -275
- package/src/assets/solana/idl/stake_controller.json +0 -1788
- package/src/assets/solana/idl/stake_registry.json +0 -435
- package/src/assets/solana/idl/treasury.json +0 -336
- package/src/assets/solana/idl/validator_registry.json +0 -418
- package/src/assets/solana/idl/yield_oracle.json +0 -32
- package/src/assets/solana/types/deposit.ts +0 -266
- package/src/assets/solana/types/distribution.ts +0 -742
- package/src/assets/solana/types/liq_sol_token.ts +0 -281
- package/src/assets/solana/types/stake_controller.ts +0 -1794
- package/src/assets/solana/types/stake_registry.ts +0 -441
- package/src/assets/solana/types/treasury.ts +0 -342
- package/src/assets/solana/types/validator_registry.ts +0 -424
- package/src/assets/solana/types/yield_oracle.ts +0 -38
- package/src/utils.ts +0 -9
|
@@ -1,113 +1,47 @@
|
|
|
1
|
-
// src/solana/programService.ts
|
|
2
|
-
|
|
3
1
|
import { AnchorProvider, Program } from '@coral-xyz/anchor';
|
|
4
|
-
import { PublicKey } from '@solana/web3.js';
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
import
|
|
8
|
-
import distributionJson from '../../assets/solana/idl/distribution.json';
|
|
9
|
-
import liqSolTokenJson from '../../assets/solana/idl/liq_sol_token.json';
|
|
10
|
-
import stakeControllerJson from '../../assets/solana/idl/stake_controller.json';
|
|
11
|
-
import stakeRegistryJson from '../../assets/solana/idl/stake_registry.json';
|
|
12
|
-
import treasuryJson from '../../assets/solana/idl/treasury.json';
|
|
3
|
+
import liqsolCoreJson from '../../assets/solana/idl/liqsol_core.json';
|
|
4
|
+
import liqsolTokenJson from '../../assets/solana/idl/liqsol_token.json';
|
|
13
5
|
import validatorLeaderboardJson from '../../assets/solana/idl/validator_leaderboard.json';
|
|
14
|
-
import validatorRegistryJson from '../../assets/solana/idl/validator_registry.json';
|
|
15
|
-
import yieldOracleJson from '../../assets/solana/idl/yield_oracle.json';
|
|
16
6
|
|
|
17
|
-
|
|
18
|
-
import type {
|
|
19
|
-
import type { Distribution } from '../../assets/solana/types/distribution';
|
|
20
|
-
import type { LiqSolToken } from '../../assets/solana/types/liq_sol_token';
|
|
21
|
-
import type { StakeController } from '../../assets/solana/types/stake_controller';
|
|
22
|
-
import type { StakeRegistry } from '../../assets/solana/types/stake_registry';
|
|
23
|
-
import type { Treasury } from '../../assets/solana/types/treasury';
|
|
7
|
+
import type { LiqsolCore } from '../../assets/solana/types/liqsol_core';
|
|
8
|
+
import type { LiqsolToken } from '../../assets/solana/types/liqsol_token';
|
|
24
9
|
import type { ValidatorLeaderboard } from '../../assets/solana/types/validator_leaderboard';
|
|
25
|
-
import type { ValidatorRegistry } from '../../assets/solana/types/validator_registry';
|
|
26
|
-
import type { YieldOracle } from '../../assets/solana/types/yield_oracle';
|
|
27
10
|
|
|
28
|
-
|
|
11
|
+
import { PROGRAM_IDS } from './constants';
|
|
12
|
+
|
|
13
|
+
type Entry<IDL> = {
|
|
29
14
|
idl: IDL & { address: string };
|
|
30
|
-
address:
|
|
15
|
+
address: string;
|
|
31
16
|
};
|
|
32
17
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
idl:
|
|
36
|
-
address:
|
|
37
|
-
} as
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
} as IdlEntry<Distribution>,
|
|
43
|
-
|
|
44
|
-
liqSolToken: {
|
|
45
|
-
idl: liqSolTokenJson,
|
|
46
|
-
address: new PublicKey(liqSolTokenJson.address),
|
|
47
|
-
} as IdlEntry<LiqSolToken>,
|
|
48
|
-
|
|
49
|
-
stakeController: {
|
|
50
|
-
idl: stakeControllerJson,
|
|
51
|
-
address: new PublicKey(stakeControllerJson.address),
|
|
52
|
-
} as IdlEntry<StakeController>,
|
|
53
|
-
|
|
54
|
-
stakeRegistry: {
|
|
55
|
-
idl: stakeRegistryJson,
|
|
56
|
-
address: new PublicKey(stakeRegistryJson.address),
|
|
57
|
-
} as IdlEntry<StakeRegistry>,
|
|
58
|
-
|
|
59
|
-
treasury: {
|
|
60
|
-
idl: treasuryJson,
|
|
61
|
-
address: new PublicKey(treasuryJson.address),
|
|
62
|
-
} as IdlEntry<Treasury>,
|
|
63
|
-
|
|
18
|
+
const PROGRAMS = {
|
|
19
|
+
liqsolCore: {
|
|
20
|
+
idl: liqsolCoreJson,
|
|
21
|
+
address: PROGRAM_IDS.LIQSOL_CORE.toBase58(),
|
|
22
|
+
} as Entry<LiqsolCore>,
|
|
23
|
+
liqsolToken: {
|
|
24
|
+
idl: liqsolTokenJson,
|
|
25
|
+
address: PROGRAM_IDS.LIQSOL_TOKEN.toBase58(),
|
|
26
|
+
} as Entry<LiqsolToken>,
|
|
64
27
|
validatorLeaderboard: {
|
|
65
28
|
idl: validatorLeaderboardJson,
|
|
66
|
-
address:
|
|
67
|
-
} as
|
|
68
|
-
|
|
69
|
-
validatorRegistry: {
|
|
70
|
-
idl: validatorRegistryJson,
|
|
71
|
-
address: new PublicKey(validatorRegistryJson.address),
|
|
72
|
-
} as IdlEntry<ValidatorRegistry>,
|
|
29
|
+
address: PROGRAM_IDS.VALIDATOR_LEADERBOARD.toBase58(),
|
|
30
|
+
} as Entry<ValidatorLeaderboard>,
|
|
31
|
+
} as const;
|
|
73
32
|
|
|
74
|
-
|
|
75
|
-
idl: yieldOracleJson,
|
|
76
|
-
address: new PublicKey(yieldOracleJson.address),
|
|
77
|
-
} as IdlEntry<YieldOracle>,
|
|
78
|
-
};
|
|
33
|
+
export type SolanaProgramName = keyof typeof PROGRAMS;
|
|
79
34
|
|
|
80
|
-
/**
|
|
81
|
-
* Factory for Anchor Program clients.
|
|
82
|
-
*
|
|
83
|
-
* Anchor v0.28+ reads the program ID from `idl.address`, so
|
|
84
|
-
* we call the 2-arg constructor: `new Program(idl, provider)`.
|
|
85
|
-
*/
|
|
86
35
|
export class SolanaProgramService {
|
|
87
36
|
constructor(private provider: AnchorProvider) { }
|
|
88
37
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
name: K
|
|
94
|
-
): Program<(typeof PROGRAM_IDLS)[K]['idl']> {
|
|
95
|
-
const entry = PROGRAM_IDLS[name];
|
|
96
|
-
// stamp the correct address into a fresh copy of the IDL
|
|
97
|
-
const idlWithAddr = { ...entry.idl, address: entry.address.toString() };
|
|
98
|
-
// use the two-arg signature: (idl, provider)
|
|
99
|
-
return new Program(idlWithAddr as any, this.provider) as Program<
|
|
100
|
-
(typeof PROGRAM_IDLS)[K]['idl']
|
|
101
|
-
>;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** List all program keys */
|
|
105
|
-
listProgramNames(): Array<keyof typeof PROGRAM_IDLS> {
|
|
106
|
-
return Object.keys(PROGRAM_IDLS) as Array<keyof typeof PROGRAM_IDLS>;
|
|
38
|
+
getProgram<K extends SolanaProgramName>(name: K): Program<(typeof PROGRAMS)[K]['idl']> {
|
|
39
|
+
const { idl, address } = PROGRAMS[name];
|
|
40
|
+
const idlWithAddr = { ...idl, address };
|
|
41
|
+
return new Program(idlWithAddr, this.provider) as Program<(typeof PROGRAMS)[K]['idl']>;
|
|
107
42
|
}
|
|
108
43
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return PROGRAM_IDLS[name].address;
|
|
44
|
+
listProgramNames(): SolanaProgramName[] {
|
|
45
|
+
return Object.keys(PROGRAMS) as SolanaProgramName[];
|
|
112
46
|
}
|
|
113
47
|
}
|
|
@@ -1,57 +1,69 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Commitment,
|
|
2
3
|
Connection,
|
|
4
|
+
ConnectionConfig,
|
|
3
5
|
PublicKey as SolPubKey,
|
|
4
6
|
Transaction,
|
|
5
|
-
VersionedTransaction,
|
|
6
7
|
TransactionSignature,
|
|
7
|
-
Commitment,
|
|
8
8
|
} from '@solana/web3.js';
|
|
9
9
|
import { AnchorProvider } from '@coral-xyz/anchor';
|
|
10
10
|
import { BaseSignerWalletAdapter } from '@solana/wallet-adapter-base';
|
|
11
|
-
import {
|
|
11
|
+
import { getAssociatedTokenAddressSync, TOKEN_2022_PROGRAM_ID } from '@solana/spl-token';
|
|
12
|
+
|
|
12
13
|
import { ChainID, ExternalNetwork, KeyType, PublicKey } from '@wireio/core';
|
|
14
|
+
import { IStakingClient, Portfolio, StakerConfig } from '../../staker/types';
|
|
15
|
+
|
|
13
16
|
import { DepositClient } from './clients/deposit.client';
|
|
14
17
|
import { DistributionClient } from './clients/distribution.client';
|
|
15
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
deriveLiqsolMintPda,
|
|
20
|
+
deriveReservePoolPda,
|
|
21
|
+
deriveVaultPda,
|
|
22
|
+
} from './constants';
|
|
23
|
+
import { SolanaTransaction, UserRecord } from './types';
|
|
24
|
+
import { LeaderboardClient } from './clients/leaderboard.client';
|
|
16
25
|
|
|
17
26
|
const commitment: Commitment = 'confirmed';
|
|
18
27
|
|
|
19
28
|
export class SolanaStakingClient implements IStakingClient {
|
|
20
29
|
public pubKey: PublicKey;
|
|
21
|
-
public network: ExternalNetwork;
|
|
22
|
-
|
|
23
30
|
public connection: Connection;
|
|
24
31
|
public anchor: AnchorProvider;
|
|
25
32
|
|
|
26
33
|
private depositClient: DepositClient;
|
|
27
34
|
private distributionClient: DistributionClient;
|
|
28
|
-
private leaderboardClient:
|
|
29
|
-
|
|
30
|
-
balanceNative: number = 0;
|
|
31
|
-
balanceLiquid: number = 0;
|
|
35
|
+
private leaderboardClient: LeaderboardClient;
|
|
32
36
|
|
|
33
37
|
get solPubKey(): SolPubKey {
|
|
34
38
|
return new SolPubKey(this.pubKey.data.array);
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
get network() {
|
|
42
|
+
return this.config.network;
|
|
43
|
+
}
|
|
44
|
+
|
|
37
45
|
constructor(private config: StakerConfig) {
|
|
38
|
-
// 1) unwrap & validate wallet adapter
|
|
39
46
|
const adapter = config.provider as BaseSignerWalletAdapter;
|
|
40
47
|
if (!adapter.publicKey) {
|
|
41
48
|
throw new Error('Solana wallet adapter not connected');
|
|
42
49
|
}
|
|
50
|
+
if (!config.network.rpcUrls.length) {
|
|
51
|
+
throw new Error('No RPC URLs provided');
|
|
52
|
+
}
|
|
43
53
|
|
|
44
|
-
// 2) sanity‐check wire ↔ solana pubkey
|
|
45
54
|
const publicKey = adapter.publicKey;
|
|
46
55
|
const wirePub = new PublicKey(KeyType.ED, publicKey.toBytes());
|
|
47
56
|
if (!wirePub.equals(config.pubKey)) {
|
|
48
|
-
throw new Error(
|
|
57
|
+
throw new Error("Passed-in pubKey doesn't match adapter.publicKey");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const opts: ConnectionConfig = { commitment };
|
|
61
|
+
if (config.network.rpcUrls.length > 1 && config.network.rpcUrls[1].startsWith('ws')) {
|
|
62
|
+
opts.wsEndpoint = config.network.rpcUrls[1];
|
|
49
63
|
}
|
|
50
64
|
|
|
51
|
-
this.network = config.network;
|
|
52
65
|
this.pubKey = wirePub;
|
|
53
|
-
this.connection = new Connection(config.network.rpcUrls[0],
|
|
54
|
-
this.setBalances();
|
|
66
|
+
this.connection = new Connection(config.network.rpcUrls[0], opts);
|
|
55
67
|
|
|
56
68
|
const anchorWallet = {
|
|
57
69
|
publicKey,
|
|
@@ -63,27 +75,123 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
63
75
|
},
|
|
64
76
|
};
|
|
65
77
|
|
|
66
|
-
this.anchor = new AnchorProvider(
|
|
67
|
-
this.connection,
|
|
68
|
-
anchorWallet,
|
|
69
|
-
{ commitment }
|
|
70
|
-
);
|
|
78
|
+
this.anchor = new AnchorProvider(this.connection, anchorWallet, { commitment });
|
|
71
79
|
|
|
72
|
-
// 4) staking clients
|
|
73
80
|
this.depositClient = new DepositClient(this.anchor);
|
|
74
81
|
this.distributionClient = new DistributionClient(this.anchor);
|
|
75
|
-
this.leaderboardClient = new
|
|
82
|
+
this.leaderboardClient = new LeaderboardClient(this.anchor);
|
|
76
83
|
}
|
|
77
84
|
|
|
78
85
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
86
|
+
* Resolve the user's liqSOL ATA and balances + key protocol balances.
|
|
87
|
+
* native = SOL in wallet
|
|
88
|
+
* actual = liqSOL token balance (from ATA)
|
|
89
|
+
* tracked = liqSOL tracked balance (from Distribution.userRecord)
|
|
81
90
|
*/
|
|
82
|
-
async
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
async getPortfolio(): Promise<Portfolio> {
|
|
92
|
+
try {
|
|
93
|
+
const user = this.solPubKey;
|
|
94
|
+
const reservePoolPDA = deriveReservePoolPda();
|
|
95
|
+
const vaultPDA = deriveVaultPda();
|
|
96
|
+
const liqsolMint = deriveLiqsolMintPda();
|
|
97
|
+
const userLiqsolAta = getAssociatedTokenAddressSync(
|
|
98
|
+
liqsolMint,
|
|
99
|
+
user,
|
|
100
|
+
false,
|
|
101
|
+
TOKEN_2022_PROGRAM_ID,
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
const [nativeLamports, actualBalResp, userRecord] = await Promise.all([
|
|
105
|
+
this.connection.getBalance(user),
|
|
106
|
+
this.connection.getTokenAccountBalance(userLiqsolAta).catch(() => null),
|
|
107
|
+
this.distributionClient.getUserRecord(user).catch(() => null),
|
|
108
|
+
]);
|
|
109
|
+
|
|
110
|
+
const actualAmountStr = actualBalResp?.value?.amount ?? '0';
|
|
111
|
+
const actualDecimals = actualBalResp?.value?.decimals ?? 9;
|
|
112
|
+
|
|
113
|
+
const trackedAmountStr = userRecord?.trackedBalance
|
|
114
|
+
? userRecord.trackedBalance.toString()
|
|
115
|
+
: '0';
|
|
116
|
+
const trackedDecimals = actualDecimals;
|
|
117
|
+
|
|
118
|
+
const portfolio: Portfolio = {
|
|
119
|
+
native: {
|
|
120
|
+
symbol: 'SOL',
|
|
121
|
+
decimals: 9,
|
|
122
|
+
amount: BigInt(nativeLamports),
|
|
123
|
+
},
|
|
124
|
+
actual: {
|
|
125
|
+
symbol: 'LiqSOL',
|
|
126
|
+
decimals: actualDecimals,
|
|
127
|
+
amount: BigInt(actualAmountStr),
|
|
128
|
+
},
|
|
129
|
+
tracked: {
|
|
130
|
+
symbol: 'LiqSOL',
|
|
131
|
+
decimals: trackedDecimals,
|
|
132
|
+
amount: BigInt(trackedAmountStr),
|
|
133
|
+
},
|
|
134
|
+
extras: {
|
|
135
|
+
userLiqsolAta: userLiqsolAta.toBase58(),
|
|
136
|
+
reservePoolPDA: reservePoolPDA.toBase58(),
|
|
137
|
+
vaultPDA: vaultPDA.toBase58(),
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return portfolio;
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
console.log('Error in getPortfolio:', error);
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
85
148
|
|
|
86
|
-
|
|
149
|
+
/**
|
|
150
|
+
* Optional: fetch your Distribution program user record
|
|
151
|
+
* (often contains per-user deposit/claim state).
|
|
152
|
+
* @returns UserRecord or null
|
|
153
|
+
*/
|
|
154
|
+
async getUserRecord() {
|
|
155
|
+
return this.distributionClient.getUserRecord(this.solPubKey);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
getProtocolFee() {
|
|
159
|
+
// TODO: wire to pay-rate math once we finalize protocol fee API
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Build, sign, and submit a single transaction that:
|
|
164
|
+
* - Corrects other users (if needed) to free available balance, then
|
|
165
|
+
* - Registers the caller’s untracked liqSOL.
|
|
166
|
+
*
|
|
167
|
+
* @param amount Optional: register a smaller amount than your full untracked balance.
|
|
168
|
+
* @returns signature string
|
|
169
|
+
*/
|
|
170
|
+
async register(amount?: bigint): Promise<string> {
|
|
171
|
+
try {
|
|
172
|
+
const build = await this.distributionClient.buildCorrectRegisterTx({ amount });
|
|
173
|
+
if (!build.canSucceed || !build.transaction) {
|
|
174
|
+
throw new Error(build.reason ?? 'Unable to build Correct&Register transaction');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const { tx, blockhash, lastValidBlockHeight } = await this.prepareTx(build.transaction);
|
|
178
|
+
const signed = await this.signTransaction(tx);
|
|
179
|
+
const result = await this.sendAndConfirmHttp(signed, { blockhash, lastValidBlockHeight });
|
|
180
|
+
|
|
181
|
+
console.log('Registered:', {
|
|
182
|
+
needToRegister: build.needToRegister,
|
|
183
|
+
freed: build.plan.willFree,
|
|
184
|
+
corrected: build.plan.selected.map((c) => ({
|
|
185
|
+
owner: c.owner?.toBase58(),
|
|
186
|
+
delta: c.delta?.toString(),
|
|
187
|
+
})),
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
return result.signature;
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error('Error in register:', error);
|
|
193
|
+
throw error;
|
|
194
|
+
}
|
|
87
195
|
}
|
|
88
196
|
|
|
89
197
|
/**
|
|
@@ -92,19 +200,56 @@ export class SolanaStakingClient implements IStakingClient {
|
|
|
92
200
|
* @returns The transaction signature.
|
|
93
201
|
*/
|
|
94
202
|
async deposit(lamports: number): Promise<string> {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
203
|
+
const { transaction } = await this.depositClient.buildDepositTx(this.solPubKey, lamports);
|
|
204
|
+
const { tx, blockhash, lastValidBlockHeight } = await this.prepareTx(transaction);
|
|
205
|
+
const signed = await this.signTransaction(tx);
|
|
206
|
+
const result = await this.sendAndConfirmHttp(signed, { blockhash, lastValidBlockHeight });
|
|
207
|
+
return result.signature;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private async sendAndConfirmHttp(
|
|
211
|
+
signed: SolanaTransaction,
|
|
212
|
+
ctx: { blockhash: string; lastValidBlockHeight: number },
|
|
213
|
+
): Promise<TxResult> {
|
|
214
|
+
const signature = await this.connection.sendRawTransaction(signed.serialize(), {
|
|
215
|
+
skipPreflight: false,
|
|
216
|
+
preflightCommitment: commitment,
|
|
217
|
+
maxRetries: 3,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
const conf = await this.connection.confirmTransaction(
|
|
221
|
+
{ signature, blockhash: ctx.blockhash, lastValidBlockHeight: ctx.lastValidBlockHeight },
|
|
222
|
+
commitment,
|
|
98
223
|
);
|
|
99
|
-
|
|
100
|
-
|
|
224
|
+
|
|
225
|
+
const ok = !conf.value.err;
|
|
226
|
+
if (!ok) {
|
|
227
|
+
throw new Error(`Transaction failed: ${JSON.stringify(conf.value.err)}`);
|
|
228
|
+
}
|
|
229
|
+
return { signature, slot: conf.context.slot, confirmed: true };
|
|
101
230
|
}
|
|
102
231
|
|
|
103
232
|
async signTransaction(tx: SolanaTransaction): Promise<SolanaTransaction> {
|
|
104
|
-
return
|
|
233
|
+
return this.anchor.wallet.signTransaction(tx);
|
|
105
234
|
}
|
|
106
235
|
|
|
107
236
|
async sendTransaction(signed: SolanaTransaction): Promise<TransactionSignature> {
|
|
108
|
-
return
|
|
237
|
+
return this.anchor.sendAndConfirm(signed);
|
|
109
238
|
}
|
|
239
|
+
|
|
240
|
+
async prepareTx(
|
|
241
|
+
tx: Transaction,
|
|
242
|
+
): Promise<{ tx: Transaction; blockhash: string; lastValidBlockHeight: number }> {
|
|
243
|
+
const { blockhash, lastValidBlockHeight } = await this.connection.getLatestBlockhash('confirmed');
|
|
244
|
+
tx.recentBlockhash = blockhash;
|
|
245
|
+
tx.feePayer = this.solPubKey;
|
|
246
|
+
|
|
247
|
+
return { tx, blockhash, lastValidBlockHeight };
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export interface TxResult {
|
|
252
|
+
signature: string;
|
|
253
|
+
slot: number;
|
|
254
|
+
confirmed: boolean;
|
|
110
255
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { PublicKey, StakeActivationData, TokenAmount, Transaction, VersionedTransaction } from "@solana/web3.js";
|
|
2
|
+
|
|
3
|
+
export type SolanaTransaction = Transaction | VersionedTransaction
|
|
4
|
+
|
|
5
|
+
export type UserRecord = {
|
|
6
|
+
userAta: PublicKey;
|
|
7
|
+
trackedBalance: bigint; // What we think they have (for reward calculations)
|
|
8
|
+
claimBalance: bigint; // Accumulated unclaimed rewards
|
|
9
|
+
lastClaimTimestamp: bigint; // When they last claimed (unix timestamp)
|
|
10
|
+
bump: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type DistributionState = {
|
|
14
|
+
liqsolMint: PublicKey;
|
|
15
|
+
availableBalance: bigint;
|
|
16
|
+
totalTrackedBalance: bigint;
|
|
17
|
+
bump: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type ParsedAccountInfo = {
|
|
21
|
+
extensions: Array<{ extension: string }>;
|
|
22
|
+
isNative: boolean;
|
|
23
|
+
mint: string;
|
|
24
|
+
owner: string;
|
|
25
|
+
state: string;
|
|
26
|
+
tokenAmount: TokenAmount
|
|
27
|
+
};
|
|
28
|
+
export interface MismatchCandidate {
|
|
29
|
+
owner: PublicKey;
|
|
30
|
+
actual: bigint;
|
|
31
|
+
tracked: bigint;
|
|
32
|
+
delta: bigint; // tracked - actual
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface CorrectRegisterPlan {
|
|
36
|
+
deficit: bigint;
|
|
37
|
+
willFree: bigint;
|
|
38
|
+
selected: MismatchCandidate[];
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CorrectRegisterBuildResult {
|
|
42
|
+
needToRegister: boolean;
|
|
43
|
+
canSucceed: boolean;
|
|
44
|
+
reason?: string;
|
|
45
|
+
transaction?: Transaction;
|
|
46
|
+
plan: CorrectRegisterPlan;
|
|
47
|
+
}
|