@lobstercove/lichen-sdk 1.0.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/README.md +50 -0
- package/dist/bincode.d.ts +5 -0
- package/dist/bincode.js +91 -0
- package/dist/bountyboard.d.ts +57 -0
- package/dist/bountyboard.js +205 -0
- package/dist/connection.d.ts +482 -0
- package/dist/connection.js +813 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +27 -0
- package/dist/keypair.d.ts +40 -0
- package/dist/keypair.js +69 -0
- package/dist/lichenid.d.ts +271 -0
- package/dist/lichenid.js +628 -0
- package/dist/lichenswap.d.ts +79 -0
- package/dist/lichenswap.js +311 -0
- package/dist/pq.d.ts +57 -0
- package/dist/pq.js +178 -0
- package/dist/publickey.d.ts +35 -0
- package/dist/publickey.js +71 -0
- package/dist/sporepay.d.ts +57 -0
- package/dist/sporepay.js +208 -0
- package/dist/sporevault.d.ts +43 -0
- package/dist/sporevault.js +176 -0
- package/dist/thalllend.d.ts +51 -0
- package/dist/thalllend.js +206 -0
- package/dist/transaction.d.ts +100 -0
- package/dist/transaction.js +202 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Lichen JavaScript/TypeScript SDK
|
|
2
|
+
|
|
3
|
+
Official SDK for interacting with Lichen blockchain.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @lobstercove/lichen-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Connection, Keypair, PublicKey } from '@lobstercove/lichen-sdk';
|
|
15
|
+
|
|
16
|
+
// Connect to Lichen
|
|
17
|
+
const connection = new Connection('http://localhost:8899');
|
|
18
|
+
|
|
19
|
+
// Generate a native PQ keypair
|
|
20
|
+
const keypair = Keypair.generate();
|
|
21
|
+
console.log('Address:', keypair.pubkey().toBase58());
|
|
22
|
+
|
|
23
|
+
// Get account balance
|
|
24
|
+
const pubkey = new PublicKey('YourPublicKeyHere...');
|
|
25
|
+
const balance = await connection.getBalance(pubkey);
|
|
26
|
+
console.log(`Balance: ${balance.licn} LICN`);
|
|
27
|
+
|
|
28
|
+
// Subscribe to blocks
|
|
29
|
+
connection.onBlock((block) => {
|
|
30
|
+
console.log('New block:', block);
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Documentation
|
|
35
|
+
|
|
36
|
+
See the [JavaScript SDK reference](https://developers.lichen.network/sdk-js.html) for detailed API reference.
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- ✅ Complete RPC client (24 endpoints)
|
|
41
|
+
- ✅ WebSocket subscriptions (real-time events)
|
|
42
|
+
- ✅ Native PQ keypairs and self-contained signatures
|
|
43
|
+
- ✅ Transaction builder
|
|
44
|
+
- ✅ TypeScript types
|
|
45
|
+
- ✅ Address and PQ public-key utilities
|
|
46
|
+
- ✅ Full blockchain interaction
|
|
47
|
+
|
|
48
|
+
## License
|
|
49
|
+
|
|
50
|
+
MIT
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Message, Transaction } from './transaction.js';
|
|
2
|
+
export declare function hexToBytes(hex: string): Uint8Array;
|
|
3
|
+
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
4
|
+
export declare function encodeMessage(message: Message): Uint8Array;
|
|
5
|
+
export declare function encodeTransaction(transaction: Transaction): Uint8Array;
|
package/dist/bincode.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// Minimal bincode encoder for Lichen transactions
|
|
2
|
+
import { bytesToHex as pqBytesToHex, hexToBytes as pqHexToBytes, toPqSignature, } from './pq.js';
|
|
3
|
+
const textEncoder = new TextEncoder();
|
|
4
|
+
function encodeU64LE(value) {
|
|
5
|
+
const out = new Uint8Array(8);
|
|
6
|
+
const view = new DataView(out.buffer);
|
|
7
|
+
view.setBigUint64(0, BigInt(value), true);
|
|
8
|
+
return out;
|
|
9
|
+
}
|
|
10
|
+
function encodeU32LE(value) {
|
|
11
|
+
const out = new Uint8Array(4);
|
|
12
|
+
const view = new DataView(out.buffer);
|
|
13
|
+
view.setUint32(0, value, true);
|
|
14
|
+
return out;
|
|
15
|
+
}
|
|
16
|
+
function encodeOptionU64(value) {
|
|
17
|
+
if (value === undefined || value === null) {
|
|
18
|
+
return new Uint8Array([0x00]); // None
|
|
19
|
+
}
|
|
20
|
+
return concat([new Uint8Array([0x01]), encodeU64LE(value)]); // Some(value)
|
|
21
|
+
}
|
|
22
|
+
function concat(parts) {
|
|
23
|
+
const total = parts.reduce((sum, part) => sum + part.length, 0);
|
|
24
|
+
const out = new Uint8Array(total);
|
|
25
|
+
let offset = 0;
|
|
26
|
+
for (const part of parts) {
|
|
27
|
+
out.set(part, offset);
|
|
28
|
+
offset += part.length;
|
|
29
|
+
}
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
function encodeBytes(data) {
|
|
33
|
+
return concat([encodeU64LE(data.length), data]);
|
|
34
|
+
}
|
|
35
|
+
function encodeString(value) {
|
|
36
|
+
const encoded = textEncoder.encode(value);
|
|
37
|
+
return concat([encodeU64LE(encoded.length), encoded]);
|
|
38
|
+
}
|
|
39
|
+
function encodeVec(items) {
|
|
40
|
+
return concat([encodeU64LE(items.length), ...items]);
|
|
41
|
+
}
|
|
42
|
+
export function hexToBytes(hex) {
|
|
43
|
+
return pqHexToBytes(hex);
|
|
44
|
+
}
|
|
45
|
+
export function bytesToHex(bytes) {
|
|
46
|
+
return pqBytesToHex(bytes);
|
|
47
|
+
}
|
|
48
|
+
function encodeU8(value) {
|
|
49
|
+
return Uint8Array.of(value & 0xff);
|
|
50
|
+
}
|
|
51
|
+
function encodePubkey(pubkey) {
|
|
52
|
+
const bytes = pubkey.toBytes();
|
|
53
|
+
if (bytes.length !== 32) {
|
|
54
|
+
throw new Error('PublicKey must be 32 bytes');
|
|
55
|
+
}
|
|
56
|
+
return bytes;
|
|
57
|
+
}
|
|
58
|
+
function encodeInstruction(ix) {
|
|
59
|
+
const programId = encodePubkey(ix.programId);
|
|
60
|
+
const accounts = encodeVec(ix.accounts.map(encodePubkey));
|
|
61
|
+
const data = encodeBytes(ix.data);
|
|
62
|
+
return concat([programId, accounts, data]);
|
|
63
|
+
}
|
|
64
|
+
function encodePqPublicKey(publicKey) {
|
|
65
|
+
return concat([encodeU8(publicKey.schemeVersion), encodeBytes(publicKey.toBytes())]);
|
|
66
|
+
}
|
|
67
|
+
function encodePqSignature(signature) {
|
|
68
|
+
return concat([
|
|
69
|
+
encodeU8(signature.schemeVersion),
|
|
70
|
+
encodePqPublicKey(signature.publicKey),
|
|
71
|
+
encodeBytes(signature.toBytes()),
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
export function encodeMessage(message) {
|
|
75
|
+
const instructions = encodeVec(message.instructions.map(encodeInstruction));
|
|
76
|
+
const blockhash = hexToBytes(message.recentBlockhash);
|
|
77
|
+
if (blockhash.length !== 32) {
|
|
78
|
+
throw new Error('Blockhash must be 32 bytes');
|
|
79
|
+
}
|
|
80
|
+
const computeBudget = encodeOptionU64(message.computeBudget);
|
|
81
|
+
const computeUnitPrice = encodeOptionU64(message.computeUnitPrice);
|
|
82
|
+
return concat([instructions, blockhash, computeBudget, computeUnitPrice]);
|
|
83
|
+
}
|
|
84
|
+
export function encodeTransaction(transaction) {
|
|
85
|
+
const sigBytes = transaction.signatures.map((signature) => encodePqSignature(toPqSignature(signature)));
|
|
86
|
+
const encodedSigs = concat([encodeU64LE(sigBytes.length), ...sigBytes]);
|
|
87
|
+
const messageBytes = encodeMessage(transaction.message);
|
|
88
|
+
// tx_type: Native=0 (u32 LE)
|
|
89
|
+
const txType = encodeU32LE(0);
|
|
90
|
+
return concat([encodedSigs, messageBytes, txType]);
|
|
91
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Connection } from './connection.js';
|
|
2
|
+
import { Keypair } from './keypair.js';
|
|
3
|
+
import { PublicKey } from './publickey.js';
|
|
4
|
+
export declare const BOUNTY_STATUS_OPEN = 0;
|
|
5
|
+
export declare const BOUNTY_STATUS_COMPLETED = 1;
|
|
6
|
+
export declare const BOUNTY_STATUS_CANCELLED = 2;
|
|
7
|
+
export interface BountyBoardBountyInfo {
|
|
8
|
+
creator: PublicKey;
|
|
9
|
+
titleHash: Uint8Array;
|
|
10
|
+
rewardAmount: bigint;
|
|
11
|
+
deadlineSlot: bigint;
|
|
12
|
+
status: number;
|
|
13
|
+
submissionCount: number;
|
|
14
|
+
createdSlot: bigint;
|
|
15
|
+
approvedIdx: number;
|
|
16
|
+
}
|
|
17
|
+
export interface BountyBoardPlatformStats {
|
|
18
|
+
bountyCount: bigint;
|
|
19
|
+
completedCount: bigint;
|
|
20
|
+
rewardVolume: bigint;
|
|
21
|
+
cancelCount: bigint;
|
|
22
|
+
}
|
|
23
|
+
export interface BountyBoardStats {
|
|
24
|
+
bountyCount: number;
|
|
25
|
+
completedCount: number;
|
|
26
|
+
totalRewardVolume: number;
|
|
27
|
+
cancelCount: number;
|
|
28
|
+
paused: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface CreateBountyParams {
|
|
31
|
+
titleHash: Uint8Array;
|
|
32
|
+
rewardAmount: number | bigint;
|
|
33
|
+
deadlineSlot: number | bigint;
|
|
34
|
+
}
|
|
35
|
+
export interface SubmitWorkParams {
|
|
36
|
+
bountyId: number | bigint;
|
|
37
|
+
proofHash: Uint8Array;
|
|
38
|
+
}
|
|
39
|
+
export interface ApproveWorkParams {
|
|
40
|
+
bountyId: number | bigint;
|
|
41
|
+
submissionIdx: number;
|
|
42
|
+
}
|
|
43
|
+
export declare class BountyBoardClient {
|
|
44
|
+
private readonly connection;
|
|
45
|
+
private resolvedProgram?;
|
|
46
|
+
constructor(connection: Connection, programId?: PublicKey);
|
|
47
|
+
private callReadonly;
|
|
48
|
+
getProgramId(): Promise<PublicKey>;
|
|
49
|
+
getBounty(bountyId: number | bigint): Promise<BountyBoardBountyInfo | null>;
|
|
50
|
+
getBountyCount(): Promise<bigint>;
|
|
51
|
+
getPlatformStats(): Promise<BountyBoardPlatformStats>;
|
|
52
|
+
getStats(): Promise<BountyBoardStats>;
|
|
53
|
+
createBounty(creator: Keypair, params: CreateBountyParams): Promise<string>;
|
|
54
|
+
submitWork(worker: Keypair, params: SubmitWorkParams): Promise<string>;
|
|
55
|
+
approveWork(creator: Keypair, params: ApproveWorkParams): Promise<string>;
|
|
56
|
+
cancelBounty(creator: Keypair, bountyId: number | bigint): Promise<string>;
|
|
57
|
+
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { PublicKey } from './publickey.js';
|
|
2
|
+
const PROGRAM_SYMBOL_CANDIDATES = ['BOUNTY', 'bounty', 'BountyBoard', 'BOUNTYBOARD', 'bountyboard'];
|
|
3
|
+
const MAX_U64 = (1n << 64n) - 1n;
|
|
4
|
+
const BOUNTY_DATA_SIZE = 91;
|
|
5
|
+
const PLATFORM_STATS_SIZE = 32;
|
|
6
|
+
// Bounty status constants
|
|
7
|
+
export const BOUNTY_STATUS_OPEN = 0;
|
|
8
|
+
export const BOUNTY_STATUS_COMPLETED = 1;
|
|
9
|
+
export const BOUNTY_STATUS_CANCELLED = 2;
|
|
10
|
+
function normalizeAddress(value) {
|
|
11
|
+
return value instanceof PublicKey ? value : new PublicKey(value);
|
|
12
|
+
}
|
|
13
|
+
function normalizeUnsignedU64(value, fieldName) {
|
|
14
|
+
const normalized = typeof value === 'bigint'
|
|
15
|
+
? value
|
|
16
|
+
: Number.isSafeInteger(value) && value >= 0
|
|
17
|
+
? BigInt(value)
|
|
18
|
+
: null;
|
|
19
|
+
if (normalized === null || normalized < 0n || normalized > MAX_U64) {
|
|
20
|
+
throw new Error(`${fieldName} must be a u64-safe integer value`);
|
|
21
|
+
}
|
|
22
|
+
return normalized;
|
|
23
|
+
}
|
|
24
|
+
function u64LE(value, fieldName) {
|
|
25
|
+
const out = new Uint8Array(8);
|
|
26
|
+
new DataView(out.buffer).setBigUint64(0, normalizeUnsignedU64(value, fieldName), true);
|
|
27
|
+
return out;
|
|
28
|
+
}
|
|
29
|
+
function buildLayoutArgs(layout, chunks) {
|
|
30
|
+
const header = Uint8Array.from([0xAB, ...layout]);
|
|
31
|
+
const total = chunks.reduce((sum, chunk) => sum + chunk.length, header.length);
|
|
32
|
+
const out = new Uint8Array(total);
|
|
33
|
+
out.set(header, 0);
|
|
34
|
+
let offset = header.length;
|
|
35
|
+
for (const chunk of chunks) {
|
|
36
|
+
out.set(chunk, offset);
|
|
37
|
+
offset += chunk.length;
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
function decodeReturnData(returnData) {
|
|
42
|
+
return Uint8Array.from(Buffer.from(returnData, 'base64'));
|
|
43
|
+
}
|
|
44
|
+
function readU64(bytes, offset) {
|
|
45
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
46
|
+
return view.getBigUint64(offset, true);
|
|
47
|
+
}
|
|
48
|
+
function ensureReadonlySuccess(result, functionName, allowedReturnCodes = [0]) {
|
|
49
|
+
const code = result.returnCode ?? 0;
|
|
50
|
+
if (!allowedReturnCodes.includes(code)) {
|
|
51
|
+
throw new Error(result.error ?? `BountyBoard ${functionName} returned code ${code}`);
|
|
52
|
+
}
|
|
53
|
+
if (result.success === false && result.error) {
|
|
54
|
+
throw new Error(result.error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function ensureBytes32(value, fieldName) {
|
|
58
|
+
if (value.length !== 32) {
|
|
59
|
+
throw new Error(`${fieldName} must be exactly 32 bytes`);
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
// --- Encoding helpers ---
|
|
64
|
+
function encodeCreateBountyArgs(creator, titleHash, rewardAmount, deadlineSlot) {
|
|
65
|
+
return buildLayoutArgs([0x20, 0x20, 0x08, 0x08], [creator.toBytes(), ensureBytes32(titleHash, 'titleHash'), u64LE(rewardAmount, 'rewardAmount'), u64LE(deadlineSlot, 'deadlineSlot')]);
|
|
66
|
+
}
|
|
67
|
+
function encodeSubmitWorkArgs(bountyId, worker, proofHash) {
|
|
68
|
+
return buildLayoutArgs([0x08, 0x20, 0x20], [u64LE(bountyId, 'bountyId'), worker.toBytes(), ensureBytes32(proofHash, 'proofHash')]);
|
|
69
|
+
}
|
|
70
|
+
function encodeApproveWorkArgs(caller, bountyId, submissionIdx) {
|
|
71
|
+
if (submissionIdx < 0 || submissionIdx > 255) {
|
|
72
|
+
throw new Error('submissionIdx must be 0-255');
|
|
73
|
+
}
|
|
74
|
+
return buildLayoutArgs([0x20, 0x08, 0x01], [caller.toBytes(), u64LE(bountyId, 'bountyId'), Uint8Array.from([submissionIdx])]);
|
|
75
|
+
}
|
|
76
|
+
function encodeCancelBountyArgs(caller, bountyId) {
|
|
77
|
+
return buildLayoutArgs([0x20, 0x08], [caller.toBytes(), u64LE(bountyId, 'bountyId')]);
|
|
78
|
+
}
|
|
79
|
+
function encodeBountyIdArgs(bountyId) {
|
|
80
|
+
return buildLayoutArgs([0x08], [u64LE(bountyId, 'bountyId')]);
|
|
81
|
+
}
|
|
82
|
+
// --- Decoding helpers ---
|
|
83
|
+
function decodeBountyInfo(result) {
|
|
84
|
+
ensureReadonlySuccess(result, 'get_bounty');
|
|
85
|
+
if (!result.returnData) {
|
|
86
|
+
throw new Error('BountyBoard get_bounty did not return bounty data');
|
|
87
|
+
}
|
|
88
|
+
const bytes = decodeReturnData(result.returnData);
|
|
89
|
+
if (bytes.length < BOUNTY_DATA_SIZE) {
|
|
90
|
+
throw new Error('BountyBoard get_bounty payload was shorter than expected');
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
creator: new PublicKey(bytes.slice(0, 32)),
|
|
94
|
+
titleHash: bytes.slice(32, 64),
|
|
95
|
+
rewardAmount: readU64(bytes, 64),
|
|
96
|
+
deadlineSlot: readU64(bytes, 72),
|
|
97
|
+
status: bytes[80],
|
|
98
|
+
submissionCount: bytes[81],
|
|
99
|
+
createdSlot: readU64(bytes, 82),
|
|
100
|
+
approvedIdx: bytes[90],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function decodePlatformStats(result) {
|
|
104
|
+
ensureReadonlySuccess(result, 'get_platform_stats');
|
|
105
|
+
if (!result.returnData) {
|
|
106
|
+
throw new Error('BountyBoard get_platform_stats did not return stats data');
|
|
107
|
+
}
|
|
108
|
+
const bytes = decodeReturnData(result.returnData);
|
|
109
|
+
if (bytes.length < PLATFORM_STATS_SIZE) {
|
|
110
|
+
throw new Error('BountyBoard get_platform_stats payload was shorter than expected');
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
bountyCount: readU64(bytes, 0),
|
|
114
|
+
completedCount: readU64(bytes, 8),
|
|
115
|
+
rewardVolume: readU64(bytes, 16),
|
|
116
|
+
cancelCount: readU64(bytes, 24),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
export class BountyBoardClient {
|
|
120
|
+
constructor(connection, programId) {
|
|
121
|
+
this.connection = connection;
|
|
122
|
+
this.resolvedProgram = programId;
|
|
123
|
+
}
|
|
124
|
+
async callReadonly(functionName, args = new Uint8Array()) {
|
|
125
|
+
const programId = await this.getProgramId();
|
|
126
|
+
return this.connection.callReadonlyContract(programId, functionName, args);
|
|
127
|
+
}
|
|
128
|
+
async getProgramId() {
|
|
129
|
+
if (this.resolvedProgram) {
|
|
130
|
+
return this.resolvedProgram;
|
|
131
|
+
}
|
|
132
|
+
for (const symbol of PROGRAM_SYMBOL_CANDIDATES) {
|
|
133
|
+
try {
|
|
134
|
+
const entry = await this.connection.getSymbolRegistry(symbol);
|
|
135
|
+
if (entry?.program) {
|
|
136
|
+
this.resolvedProgram = new PublicKey(entry.program);
|
|
137
|
+
return this.resolvedProgram;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Try the next known registry alias.
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
throw new Error('Unable to resolve the BountyBoard program via getSymbolRegistry("BOUNTY")');
|
|
145
|
+
}
|
|
146
|
+
// --- Read methods ---
|
|
147
|
+
async getBounty(bountyId) {
|
|
148
|
+
const result = await this.callReadonly('get_bounty', encodeBountyIdArgs(normalizeUnsignedU64(bountyId, 'bountyId')));
|
|
149
|
+
if ((result.returnCode ?? 0) === 1 || !result.returnData) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
return decodeBountyInfo(result);
|
|
153
|
+
}
|
|
154
|
+
async getBountyCount() {
|
|
155
|
+
const result = await this.callReadonly('get_bounty_count');
|
|
156
|
+
ensureReadonlySuccess(result, 'get_bounty_count');
|
|
157
|
+
if (!result.returnData) {
|
|
158
|
+
return 0n;
|
|
159
|
+
}
|
|
160
|
+
const bytes = decodeReturnData(result.returnData);
|
|
161
|
+
if (bytes.length < 8) {
|
|
162
|
+
return 0n;
|
|
163
|
+
}
|
|
164
|
+
return readU64(bytes, 0);
|
|
165
|
+
}
|
|
166
|
+
async getPlatformStats() {
|
|
167
|
+
return decodePlatformStats(await this.callReadonly('get_platform_stats'));
|
|
168
|
+
}
|
|
169
|
+
async getStats() {
|
|
170
|
+
const stats = await this.connection.getBountyBoardStats();
|
|
171
|
+
return {
|
|
172
|
+
bountyCount: stats.bounty_count ?? 0,
|
|
173
|
+
completedCount: stats.completed_count ?? 0,
|
|
174
|
+
totalRewardVolume: stats.total_reward_volume ?? 0,
|
|
175
|
+
cancelCount: stats.cancel_count ?? 0,
|
|
176
|
+
paused: Boolean(stats.paused),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
// --- Write methods ---
|
|
180
|
+
async createBounty(creator, params) {
|
|
181
|
+
const programId = await this.getProgramId();
|
|
182
|
+
const rewardAmount = normalizeUnsignedU64(params.rewardAmount, 'rewardAmount');
|
|
183
|
+
const deadlineSlot = normalizeUnsignedU64(params.deadlineSlot, 'deadlineSlot');
|
|
184
|
+
const args = encodeCreateBountyArgs(creator.pubkey(), params.titleHash, rewardAmount, deadlineSlot);
|
|
185
|
+
return this.connection.callContract(creator, programId, 'create_bounty', args, rewardAmount);
|
|
186
|
+
}
|
|
187
|
+
async submitWork(worker, params) {
|
|
188
|
+
const programId = await this.getProgramId();
|
|
189
|
+
const bountyId = normalizeUnsignedU64(params.bountyId, 'bountyId');
|
|
190
|
+
const args = encodeSubmitWorkArgs(bountyId, worker.pubkey(), params.proofHash);
|
|
191
|
+
return this.connection.callContract(worker, programId, 'submit_work', args);
|
|
192
|
+
}
|
|
193
|
+
async approveWork(creator, params) {
|
|
194
|
+
const programId = await this.getProgramId();
|
|
195
|
+
const bountyId = normalizeUnsignedU64(params.bountyId, 'bountyId');
|
|
196
|
+
const args = encodeApproveWorkArgs(creator.pubkey(), bountyId, params.submissionIdx);
|
|
197
|
+
return this.connection.callContract(creator, programId, 'approve_work', args);
|
|
198
|
+
}
|
|
199
|
+
async cancelBounty(creator, bountyId) {
|
|
200
|
+
const programId = await this.getProgramId();
|
|
201
|
+
const normalizedId = normalizeUnsignedU64(bountyId, 'bountyId');
|
|
202
|
+
const args = encodeCancelBountyArgs(creator.pubkey(), normalizedId);
|
|
203
|
+
return this.connection.callContract(creator, programId, 'cancel_bounty', args);
|
|
204
|
+
}
|
|
205
|
+
}
|