@zebec-network/zebec-stream-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/LICENSE +21 -0
- package/README.md +354 -0
- package/dist/artifacts/index.d.ts +3 -0
- package/dist/artifacts/index.js +9 -0
- package/dist/artifacts/zebec_stream.d.ts +1307 -0
- package/dist/artifacts/zebec_stream.js +2 -0
- package/dist/artifacts/zebec_stream.json +1061 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.js +4 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +21 -0
- package/dist/pda.d.ts +4 -0
- package/dist/pda.js +15 -0
- package/dist/providers.d.ts +17 -0
- package/dist/providers.js +24 -0
- package/dist/service.d.ts +108 -0
- package/dist/service.js +337 -0
- package/dist/types.d.ts +43 -0
- package/dist/types.js +2 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const STREAM_NAME_BUFFER_SIZE = 128;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./artifacts"), exports);
|
|
18
|
+
__exportStar(require("./pda"), exports);
|
|
19
|
+
__exportStar(require("./providers"), exports);
|
|
20
|
+
__exportStar(require("./service"), exports);
|
|
21
|
+
__exportStar(require("./types"), exports);
|
package/dist/pda.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Address } from "@coral-xyz/anchor";
|
|
2
|
+
import { PublicKey } from "@solana/web3.js";
|
|
3
|
+
export declare function deriveStreamConfigPda(programId: Address): [PublicKey, number];
|
|
4
|
+
export declare function deriveStreamVaultPda(metatadata: Address, programId: Address): [PublicKey, number];
|
package/dist/pda.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.deriveStreamConfigPda = deriveStreamConfigPda;
|
|
4
|
+
exports.deriveStreamVaultPda = deriveStreamVaultPda;
|
|
5
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
6
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
7
|
+
const SEEDS = {
|
|
8
|
+
STREAM_CONFIG: [99, 111, 110, 102, 105, 103],
|
|
9
|
+
};
|
|
10
|
+
function deriveStreamConfigPda(programId) {
|
|
11
|
+
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(SEEDS.STREAM_CONFIG)], (0, anchor_1.translateAddress)(programId));
|
|
12
|
+
}
|
|
13
|
+
function deriveStreamVaultPda(metatadata, programId) {
|
|
14
|
+
return web3_js_1.PublicKey.findProgramAddressSync([(0, anchor_1.translateAddress)(metatadata).toBuffer()], (0, anchor_1.translateAddress)(programId));
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Address, AnchorProvider } from "@coral-xyz/anchor";
|
|
2
|
+
import { ConfirmOptions, Connection, PublicKey, Transaction, VersionedTransaction } from "@solana/web3.js";
|
|
3
|
+
export declare class ReadonlyProvider {
|
|
4
|
+
readonly connection: Connection;
|
|
5
|
+
readonly walletAddress?: PublicKey;
|
|
6
|
+
constructor(connection: Connection, walletAddress?: Address);
|
|
7
|
+
}
|
|
8
|
+
export declare function createReadonlyProvider(connection: Connection, walletAddress?: Address): ReadonlyProvider;
|
|
9
|
+
/**
|
|
10
|
+
* Wallet interface used by Anchor Framework
|
|
11
|
+
*/
|
|
12
|
+
export interface AnchorWallet {
|
|
13
|
+
signTransaction: <T extends Transaction | VersionedTransaction>(tx: T) => Promise<T>;
|
|
14
|
+
signAllTransactions: <T extends Transaction | VersionedTransaction>(txs: T[]) => Promise<T[]>;
|
|
15
|
+
publicKey: PublicKey;
|
|
16
|
+
}
|
|
17
|
+
export declare function createAnchorProvider(connection: Connection, wallet: AnchorWallet, options?: ConfirmOptions): AnchorProvider;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReadonlyProvider = void 0;
|
|
4
|
+
exports.createReadonlyProvider = createReadonlyProvider;
|
|
5
|
+
exports.createAnchorProvider = createAnchorProvider;
|
|
6
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
7
|
+
class ReadonlyProvider {
|
|
8
|
+
connection;
|
|
9
|
+
walletAddress;
|
|
10
|
+
constructor(connection, walletAddress) {
|
|
11
|
+
this.connection = connection;
|
|
12
|
+
this.walletAddress = walletAddress ? (0, anchor_1.translateAddress)(walletAddress) : undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.ReadonlyProvider = ReadonlyProvider;
|
|
16
|
+
function createReadonlyProvider(connection, walletAddress) {
|
|
17
|
+
return new ReadonlyProvider(connection, walletAddress);
|
|
18
|
+
}
|
|
19
|
+
function createAnchorProvider(connection, wallet, options) {
|
|
20
|
+
return new anchor_1.AnchorProvider(connection, wallet, {
|
|
21
|
+
...anchor_1.AnchorProvider.defaultOptions(),
|
|
22
|
+
...options,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Address, BN, Program, Provider } from "@coral-xyz/anchor";
|
|
2
|
+
import { Commitment, Keypair, PublicKey, TransactionInstruction } from "@solana/web3.js";
|
|
3
|
+
import { TransactionPayload } from "@zebec-network/solana-common";
|
|
4
|
+
import { ZebecStreamIdl } from "./artifacts";
|
|
5
|
+
import { Numeric, StreamConfigInfo, StreamMetadataInfo } from "./types";
|
|
6
|
+
export declare class ZebecStreamService {
|
|
7
|
+
readonly provider: Provider;
|
|
8
|
+
readonly network: "mainnet-beta" | "devnet";
|
|
9
|
+
readonly program: Program<ZebecStreamIdl>;
|
|
10
|
+
constructor(provider: Provider, network: "mainnet-beta" | "devnet", program: Program<ZebecStreamIdl>);
|
|
11
|
+
static create(provider: Provider, network: "mainnet-beta" | "devnet"): ZebecStreamService;
|
|
12
|
+
private _createPayload;
|
|
13
|
+
get connection(): import("@solana/web3.js").Connection;
|
|
14
|
+
get programId(): PublicKey;
|
|
15
|
+
getInitializeConfigInstruction(admin: PublicKey, config: {
|
|
16
|
+
baseFee: BN;
|
|
17
|
+
frequencies: BN[];
|
|
18
|
+
platformFee: BN;
|
|
19
|
+
withdrawAccount: PublicKey;
|
|
20
|
+
}): Promise<TransactionInstruction>;
|
|
21
|
+
getCreateStreamInstruction(feePayer: PublicKey, receiver: PublicKey, senderAta: PublicKey, streamToken: PublicKey, withdrawAccount: PublicKey, sender: PublicKey, streamMetadata: PublicKey, streamData: {
|
|
22
|
+
amount: BN;
|
|
23
|
+
automaticWithdrawal: boolean;
|
|
24
|
+
cancelableByRecipient: boolean;
|
|
25
|
+
cancelableBySender: boolean;
|
|
26
|
+
canTopup: boolean;
|
|
27
|
+
cliffPercentage: BN;
|
|
28
|
+
duration: BN;
|
|
29
|
+
isPausable: boolean;
|
|
30
|
+
rateUpdatable: boolean;
|
|
31
|
+
startNow: boolean;
|
|
32
|
+
startTime: BN;
|
|
33
|
+
streamFrequency: BN;
|
|
34
|
+
streamName: Uint8Array | Buffer;
|
|
35
|
+
transferableByRecipient: boolean;
|
|
36
|
+
transferableBySender: boolean;
|
|
37
|
+
numberOfWithdrawls: BN;
|
|
38
|
+
}): Promise<TransactionInstruction>;
|
|
39
|
+
getPauseResumeStreamInstruction(streamMetadata: PublicKey, user: PublicKey): Promise<TransactionInstruction>;
|
|
40
|
+
getCancelStreamInstruction(feePayer: PublicKey, otherParty: PublicKey, otherPartyAta: PublicKey, signer: PublicKey, signerAta: PublicKey, streamMetadata: PublicKey, streamToken: PublicKey, streamVault: PublicKey, streamVaultAta: PublicKey): Promise<TransactionInstruction>;
|
|
41
|
+
getWithdrawStreamInstruction(receiver: PublicKey, receiverAta: PublicKey, streamMetadata: PublicKey, streamToken: PublicKey, streamVault: PublicKey, streamVaultAta: PublicKey, withdrawer: PublicKey): Promise<TransactionInstruction>;
|
|
42
|
+
getWhitelistTokensInstruction(admin: PublicKey, tokens: PublicKey[]): Promise<TransactionInstruction>;
|
|
43
|
+
getChangeStreamReceiverInstruction(streamMetadata: PublicKey, newRecipient: PublicKey, signer: PublicKey): Promise<TransactionInstruction>;
|
|
44
|
+
initializeConfig(params: InitializeConfigParams): Promise<TransactionPayload>;
|
|
45
|
+
createStream(params: CreateStreamParams): Promise<TransactionPayload>;
|
|
46
|
+
cancelStream(params: CancelStreamParams): Promise<TransactionPayload>;
|
|
47
|
+
pauseResumeStream(params: {
|
|
48
|
+
streamMetadata: Address;
|
|
49
|
+
}): Promise<TransactionPayload>;
|
|
50
|
+
withdrawStream(params: WithdrawStreamParams): Promise<TransactionPayload>;
|
|
51
|
+
whiteListTokens(params: WhiteListTokensParams): Promise<TransactionPayload>;
|
|
52
|
+
changeStreamReceiver(params: ChangeStreamReceiverParams): Promise<TransactionPayload>;
|
|
53
|
+
getStreamConfigInfo(commitment?: Commitment): Promise<StreamConfigInfo>;
|
|
54
|
+
getStreamMetadataInfo(streamMetadata: Address, commitment?: Commitment): Promise<StreamMetadataInfo>;
|
|
55
|
+
}
|
|
56
|
+
export type CreateStreamParams = {
|
|
57
|
+
feePayer?: Address;
|
|
58
|
+
receiver: Address;
|
|
59
|
+
sender: Address;
|
|
60
|
+
streamToken: Address;
|
|
61
|
+
amount: Numeric;
|
|
62
|
+
automaticWithdrawal: boolean;
|
|
63
|
+
cancelableByRecipient: boolean;
|
|
64
|
+
cancelableBySender: boolean;
|
|
65
|
+
cliffPercentage: Numeric;
|
|
66
|
+
duration: number;
|
|
67
|
+
isPausable: boolean;
|
|
68
|
+
startNow: boolean;
|
|
69
|
+
startTime: number;
|
|
70
|
+
streamFrequency: number;
|
|
71
|
+
streamName: string;
|
|
72
|
+
transferableByRecipient: boolean;
|
|
73
|
+
transferableBySender: boolean;
|
|
74
|
+
canTopup: boolean;
|
|
75
|
+
rateUpdatable: boolean;
|
|
76
|
+
streamMetadataKeypair?: Keypair;
|
|
77
|
+
};
|
|
78
|
+
export type InitializeConfigParams = {
|
|
79
|
+
admin?: Address;
|
|
80
|
+
config: {
|
|
81
|
+
baseFeePercent: Numeric;
|
|
82
|
+
frequencies: number[];
|
|
83
|
+
platformFeePercent: Numeric;
|
|
84
|
+
withdrawAccount: Address;
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
export type CancelStreamParams = {
|
|
88
|
+
feePayer?: Address;
|
|
89
|
+
streamMetadata: Address;
|
|
90
|
+
user: Address;
|
|
91
|
+
};
|
|
92
|
+
export type PauseResumeStreamParams = {
|
|
93
|
+
streamMetadata: Address;
|
|
94
|
+
};
|
|
95
|
+
export type WithdrawStreamParams = {
|
|
96
|
+
streamMetadata: Address;
|
|
97
|
+
withdrawer?: Address;
|
|
98
|
+
receiver: Address;
|
|
99
|
+
};
|
|
100
|
+
export type WhiteListTokensParams = {
|
|
101
|
+
admin: Address;
|
|
102
|
+
tokens: Address[];
|
|
103
|
+
};
|
|
104
|
+
export type ChangeStreamReceiverParams = {
|
|
105
|
+
streamMetadata: Address;
|
|
106
|
+
newRecipient: Address;
|
|
107
|
+
signer: Address;
|
|
108
|
+
};
|
package/dist/service.js
ADDED
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.ZebecStreamService = void 0;
|
|
7
|
+
const assert_1 = __importDefault(require("assert"));
|
|
8
|
+
const bignumber_js_1 = require("bignumber.js");
|
|
9
|
+
const anchor_1 = require("@coral-xyz/anchor");
|
|
10
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
11
|
+
const core_utils_1 = require("@zebec-network/core-utils");
|
|
12
|
+
const solana_common_1 = require("@zebec-network/solana-common");
|
|
13
|
+
const artifacts_1 = require("./artifacts");
|
|
14
|
+
const constants_1 = require("./constants");
|
|
15
|
+
const pda_1 = require("./pda");
|
|
16
|
+
class ZebecStreamService {
|
|
17
|
+
provider;
|
|
18
|
+
network;
|
|
19
|
+
program;
|
|
20
|
+
constructor(provider, network, program) {
|
|
21
|
+
this.provider = provider;
|
|
22
|
+
this.network = network;
|
|
23
|
+
this.program = program;
|
|
24
|
+
}
|
|
25
|
+
static create(provider, network) {
|
|
26
|
+
const connection = provider.connection;
|
|
27
|
+
const rpcEndpoint = connection.rpcEndpoint;
|
|
28
|
+
const connNetwork = rpcEndpoint.includes("devnet")
|
|
29
|
+
? "devnet"
|
|
30
|
+
: rpcEndpoint.includes("testnet")
|
|
31
|
+
? "testnet"
|
|
32
|
+
: "mainnet-beta";
|
|
33
|
+
if (connNetwork === "testnet") {
|
|
34
|
+
throw new Error("InvalidOperation: Testnet is not supported. Please use connection with devnet or mainnet-beta network.");
|
|
35
|
+
}
|
|
36
|
+
if (network !== connNetwork) {
|
|
37
|
+
throw new Error(`InvalidOperation: Network mismatch. network and connection network should be same. network: ${network}, connection: ${connNetwork}`);
|
|
38
|
+
}
|
|
39
|
+
const program = new anchor_1.Program(artifacts_1.ZEBEC_STREAM_IDL, provider);
|
|
40
|
+
return new ZebecStreamService(provider, network, program);
|
|
41
|
+
}
|
|
42
|
+
async _createPayload(payerKey, instructions, signers, addressLookupTableAccounts) {
|
|
43
|
+
const errorMap = new Map();
|
|
44
|
+
this.program.idl.errors.forEach((error) => errorMap.set(error.code, error.msg));
|
|
45
|
+
const provider = this.provider;
|
|
46
|
+
let signTransaction;
|
|
47
|
+
if (provider instanceof anchor_1.AnchorProvider) {
|
|
48
|
+
signTransaction = async (tx) => {
|
|
49
|
+
return provider.wallet.signTransaction(tx);
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return new solana_common_1.TransactionPayload(this.connection, errorMap, instructions, payerKey, signers, addressLookupTableAccounts, signTransaction);
|
|
53
|
+
}
|
|
54
|
+
get connection() {
|
|
55
|
+
return this.provider.connection;
|
|
56
|
+
}
|
|
57
|
+
get programId() {
|
|
58
|
+
return this.program.programId;
|
|
59
|
+
}
|
|
60
|
+
async getInitializeConfigInstruction(admin, config) {
|
|
61
|
+
return this.program.methods
|
|
62
|
+
.initializeConfig({
|
|
63
|
+
baseFee: config.baseFee,
|
|
64
|
+
frequencies: config.frequencies,
|
|
65
|
+
platformFee: config.platformFee,
|
|
66
|
+
withdrawAccount: config.withdrawAccount,
|
|
67
|
+
})
|
|
68
|
+
.accounts({
|
|
69
|
+
admin,
|
|
70
|
+
})
|
|
71
|
+
.instruction();
|
|
72
|
+
}
|
|
73
|
+
getCreateStreamInstruction(feePayer, receiver, senderAta, streamToken, withdrawAccount, sender, streamMetadata, streamData) {
|
|
74
|
+
(0, assert_1.default)(streamData.streamName.length === constants_1.STREAM_NAME_BUFFER_SIZE, `Stream name buffer must be of size ${constants_1.STREAM_NAME_BUFFER_SIZE}`);
|
|
75
|
+
return this.program.methods
|
|
76
|
+
.createStream({
|
|
77
|
+
amount: streamData.amount,
|
|
78
|
+
automaticWithdrawal: Number(streamData.automaticWithdrawal),
|
|
79
|
+
cancelableByRecipient: Number(streamData.cancelableByRecipient),
|
|
80
|
+
cancelableBySender: Number(streamData.cancelableBySender),
|
|
81
|
+
canTopup: Number(streamData.canTopup),
|
|
82
|
+
cliffPercentage: streamData.cliffPercentage,
|
|
83
|
+
duration: streamData.duration,
|
|
84
|
+
isPausable: Number(streamData.isPausable),
|
|
85
|
+
rateUpdatable: Number(streamData.rateUpdatable),
|
|
86
|
+
receiver,
|
|
87
|
+
sender,
|
|
88
|
+
startNow: Number(streamData.startNow),
|
|
89
|
+
startTime: streamData.startTime,
|
|
90
|
+
streamFrequency: streamData.streamFrequency,
|
|
91
|
+
streamName: Array.from(streamData.streamName),
|
|
92
|
+
transferableByRecipient: Number(streamData.transferableByRecipient),
|
|
93
|
+
transferableBySender: Number(streamData.transferableBySender),
|
|
94
|
+
})
|
|
95
|
+
.accountsPartial({
|
|
96
|
+
feePayer,
|
|
97
|
+
receiver,
|
|
98
|
+
senderAta,
|
|
99
|
+
streamToken,
|
|
100
|
+
withdrawAccount,
|
|
101
|
+
sender,
|
|
102
|
+
streamMetadata,
|
|
103
|
+
})
|
|
104
|
+
.instruction();
|
|
105
|
+
}
|
|
106
|
+
getPauseResumeStreamInstruction(streamMetadata, user) {
|
|
107
|
+
return this.program.methods
|
|
108
|
+
.pauseResumeStream()
|
|
109
|
+
.accounts({
|
|
110
|
+
streamMetadata,
|
|
111
|
+
user,
|
|
112
|
+
})
|
|
113
|
+
.instruction();
|
|
114
|
+
}
|
|
115
|
+
getCancelStreamInstruction(feePayer, otherParty, otherPartyAta, signer, signerAta, streamMetadata, streamToken, streamVault, streamVaultAta) {
|
|
116
|
+
return this.program.methods
|
|
117
|
+
.cancelStream()
|
|
118
|
+
.accountsPartial({
|
|
119
|
+
feePayer,
|
|
120
|
+
otherParty,
|
|
121
|
+
otherPartyAta,
|
|
122
|
+
signer,
|
|
123
|
+
signerAta,
|
|
124
|
+
streamMetadata,
|
|
125
|
+
streamToken,
|
|
126
|
+
streamVault,
|
|
127
|
+
streamVaultAta,
|
|
128
|
+
})
|
|
129
|
+
.instruction();
|
|
130
|
+
}
|
|
131
|
+
getWithdrawStreamInstruction(receiver, receiverAta, streamMetadata, streamToken, streamVault, streamVaultAta, withdrawer) {
|
|
132
|
+
return this.program.methods
|
|
133
|
+
.withdrawStream()
|
|
134
|
+
.accountsPartial({
|
|
135
|
+
streamMetadata,
|
|
136
|
+
streamToken,
|
|
137
|
+
streamVault,
|
|
138
|
+
streamVaultAta,
|
|
139
|
+
receiver,
|
|
140
|
+
receiverAta,
|
|
141
|
+
withdrawer,
|
|
142
|
+
})
|
|
143
|
+
.instruction();
|
|
144
|
+
}
|
|
145
|
+
async getWhitelistTokensInstruction(admin, tokens) {
|
|
146
|
+
return this.program.methods
|
|
147
|
+
.whitelistTokens({
|
|
148
|
+
tokens,
|
|
149
|
+
})
|
|
150
|
+
.accounts({
|
|
151
|
+
admin,
|
|
152
|
+
})
|
|
153
|
+
.instruction();
|
|
154
|
+
}
|
|
155
|
+
async getChangeStreamReceiverInstruction(streamMetadata, newRecipient, signer) {
|
|
156
|
+
return this.program.methods
|
|
157
|
+
.changeRecipient()
|
|
158
|
+
.accounts({
|
|
159
|
+
newRecipient,
|
|
160
|
+
stream: streamMetadata,
|
|
161
|
+
signer,
|
|
162
|
+
})
|
|
163
|
+
.instruction();
|
|
164
|
+
}
|
|
165
|
+
async initializeConfig(params) {
|
|
166
|
+
const admin = params.admin ? (0, anchor_1.translateAddress)(params.admin) : this.provider.publicKey;
|
|
167
|
+
if (!admin) {
|
|
168
|
+
throw new Error("Either provide admin or create provider with public key");
|
|
169
|
+
}
|
|
170
|
+
const baseFee = new anchor_1.BN((0, core_utils_1.percentToBps)(params.config.baseFeePercent));
|
|
171
|
+
const frequencies = params.config.frequencies.map((frequency) => new anchor_1.BN(frequency));
|
|
172
|
+
const platformFee = new anchor_1.BN((0, core_utils_1.percentToBps)(params.config.platformFeePercent));
|
|
173
|
+
const withdrawAccount = (0, anchor_1.translateAddress)(params.config.withdrawAccount);
|
|
174
|
+
const ix = await this.getInitializeConfigInstruction(admin, {
|
|
175
|
+
baseFee,
|
|
176
|
+
frequencies,
|
|
177
|
+
platformFee,
|
|
178
|
+
withdrawAccount,
|
|
179
|
+
});
|
|
180
|
+
return this._createPayload(admin, [ix]);
|
|
181
|
+
}
|
|
182
|
+
async createStream(params) {
|
|
183
|
+
const receiver = (0, anchor_1.translateAddress)(params.receiver);
|
|
184
|
+
const sender = (0, anchor_1.translateAddress)(params.sender);
|
|
185
|
+
const feePayer = params.feePayer ? (0, anchor_1.translateAddress)(params.feePayer) : sender;
|
|
186
|
+
const streamToken = (0, anchor_1.translateAddress)(params.streamToken);
|
|
187
|
+
const [streamConfig] = (0, pda_1.deriveStreamConfigPda)(this.programId);
|
|
188
|
+
const streamConfigAccount = await this.program.account.streamConfig.fetch(streamConfig);
|
|
189
|
+
const withdrawer = streamConfigAccount.withdrawAccount;
|
|
190
|
+
const streamFrequencies = new Set(Array.from(streamConfigAccount.frequencies.map((f) => f.toNumber())));
|
|
191
|
+
if (!streamFrequencies.has(params.streamFrequency)) {
|
|
192
|
+
throw new Error("Invalid stream frequency");
|
|
193
|
+
}
|
|
194
|
+
const senderAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, sender, true);
|
|
195
|
+
const streamMetadataKeypair = params.streamMetadataKeypair ?? web3_js_1.Keypair.generate();
|
|
196
|
+
const streamTokenDecimals = await (0, solana_common_1.getMintDecimals)(this.connection, streamToken);
|
|
197
|
+
const amount = new anchor_1.BN((0, bignumber_js_1.BigNumber)(params.amount).times(solana_common_1.TEN_BIGNUM.pow(streamTokenDecimals)).toFixed(0));
|
|
198
|
+
const cliffPercentage = new anchor_1.BN((0, core_utils_1.percentToBps)(params.cliffPercentage));
|
|
199
|
+
const streamNameBuffer = Buffer.alloc(constants_1.STREAM_NAME_BUFFER_SIZE);
|
|
200
|
+
streamNameBuffer.fill(anchor_1.utils.bytes.utf8.encode(params.streamName), 0);
|
|
201
|
+
const ix = await this.getCreateStreamInstruction(feePayer, receiver, senderAta, streamToken, withdrawer, sender, streamMetadataKeypair.publicKey, {
|
|
202
|
+
amount,
|
|
203
|
+
automaticWithdrawal: params.automaticWithdrawal,
|
|
204
|
+
cancelableByRecipient: params.cancelableByRecipient,
|
|
205
|
+
cancelableBySender: params.cancelableBySender,
|
|
206
|
+
canTopup: params.canTopup,
|
|
207
|
+
cliffPercentage,
|
|
208
|
+
duration: new anchor_1.BN(params.duration),
|
|
209
|
+
isPausable: params.isPausable,
|
|
210
|
+
numberOfWithdrawls: new anchor_1.BN(params.duration / params.streamFrequency),
|
|
211
|
+
rateUpdatable: params.rateUpdatable,
|
|
212
|
+
startNow: params.startNow,
|
|
213
|
+
startTime: new anchor_1.BN(params.startTime),
|
|
214
|
+
streamFrequency: new anchor_1.BN(params.streamFrequency),
|
|
215
|
+
streamName: streamNameBuffer,
|
|
216
|
+
transferableByRecipient: params.transferableByRecipient,
|
|
217
|
+
transferableBySender: params.transferableBySender,
|
|
218
|
+
});
|
|
219
|
+
return this._createPayload(feePayer, [ix], [streamMetadataKeypair]);
|
|
220
|
+
}
|
|
221
|
+
async cancelStream(params) {
|
|
222
|
+
const user = (0, anchor_1.translateAddress)(params.user);
|
|
223
|
+
const streamMetadata = (0, anchor_1.translateAddress)(params.streamMetadata);
|
|
224
|
+
const streamMetadataAccount = await this.program.account.paymentStream.fetch(streamMetadata);
|
|
225
|
+
const streamToken = streamMetadataAccount.financials.streamToken;
|
|
226
|
+
const streamer = streamMetadataAccount.parties.sender;
|
|
227
|
+
const receiver = streamMetadataAccount.parties.receiver;
|
|
228
|
+
let otherParty;
|
|
229
|
+
if (user.equals(streamer)) {
|
|
230
|
+
otherParty = receiver;
|
|
231
|
+
}
|
|
232
|
+
else if (user.equals(receiver)) {
|
|
233
|
+
otherParty = streamer;
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
throw new Error("User must be either streamer or receiver");
|
|
237
|
+
}
|
|
238
|
+
const feePayer = params.feePayer ? (0, anchor_1.translateAddress)(params.feePayer) : user;
|
|
239
|
+
const userAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, user, true);
|
|
240
|
+
const otherPartyAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, otherParty, true);
|
|
241
|
+
const [streamVault] = (0, pda_1.deriveStreamVaultPda)(streamMetadata, this.programId);
|
|
242
|
+
const streamVaultAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, streamVault, true);
|
|
243
|
+
const ix = await this.getCancelStreamInstruction(feePayer, otherParty, otherPartyAta, user, userAta, streamMetadata, streamToken, streamVault, streamVaultAta);
|
|
244
|
+
return this._createPayload(feePayer, [ix]);
|
|
245
|
+
}
|
|
246
|
+
async pauseResumeStream(params) {
|
|
247
|
+
const streamMetadata = (0, anchor_1.translateAddress)(params.streamMetadata);
|
|
248
|
+
const streamMetadataAccount = await this.program.account.paymentStream.fetch(streamMetadata);
|
|
249
|
+
const user = streamMetadataAccount.parties.sender;
|
|
250
|
+
const ix = await this.getPauseResumeStreamInstruction(streamMetadata, user);
|
|
251
|
+
return this._createPayload(user, [ix]);
|
|
252
|
+
}
|
|
253
|
+
async withdrawStream(params) {
|
|
254
|
+
const receiver = (0, anchor_1.translateAddress)(params.receiver);
|
|
255
|
+
const withdrawer = params.withdrawer ? (0, anchor_1.translateAddress)(params.withdrawer) : receiver;
|
|
256
|
+
const streamMetadata = (0, anchor_1.translateAddress)(params.streamMetadata);
|
|
257
|
+
const streamMetadataAccount = await this.program.account.paymentStream.fetch(streamMetadata);
|
|
258
|
+
const streamToken = streamMetadataAccount.financials.streamToken;
|
|
259
|
+
const receiverAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, receiver, true);
|
|
260
|
+
const [streamVault] = (0, pda_1.deriveStreamVaultPda)(streamMetadata, this.programId);
|
|
261
|
+
const streamVaultAta = (0, solana_common_1.getAssociatedTokenAddressSync)(streamToken, streamVault, true);
|
|
262
|
+
const ix = await this.getWithdrawStreamInstruction(receiver, receiverAta, streamMetadata, streamToken, streamVault, streamVaultAta, withdrawer);
|
|
263
|
+
return this._createPayload(withdrawer, [ix]);
|
|
264
|
+
}
|
|
265
|
+
async whiteListTokens(params) {
|
|
266
|
+
const admin = (0, anchor_1.translateAddress)(params.admin);
|
|
267
|
+
const tokens = params.tokens.map((token) => (0, anchor_1.translateAddress)(token));
|
|
268
|
+
const ix = await this.getWhitelistTokensInstruction(admin, tokens);
|
|
269
|
+
return this._createPayload(admin, [ix]);
|
|
270
|
+
}
|
|
271
|
+
async changeStreamReceiver(params) {
|
|
272
|
+
const streamMetadata = (0, anchor_1.translateAddress)(params.streamMetadata);
|
|
273
|
+
const newRecipient = (0, anchor_1.translateAddress)(params.newRecipient);
|
|
274
|
+
const signer = (0, anchor_1.translateAddress)(params.signer);
|
|
275
|
+
const ix = await this.getChangeStreamReceiverInstruction(streamMetadata, newRecipient, signer);
|
|
276
|
+
return this._createPayload(signer, [ix]);
|
|
277
|
+
}
|
|
278
|
+
async getStreamConfigInfo(commitment) {
|
|
279
|
+
const [config] = (0, pda_1.deriveStreamConfigPda)(this.programId);
|
|
280
|
+
const configInfo = await this.program.account.streamConfig.fetch(config, commitment ?? this.connection.commitment);
|
|
281
|
+
return {
|
|
282
|
+
admin: configInfo.admin,
|
|
283
|
+
withdrawerAccount: configInfo.withdrawAccount,
|
|
284
|
+
whitelistedTokens: configInfo.whitelistedTokens,
|
|
285
|
+
platformFee: Number((0, core_utils_1.bpsToPercent)(configInfo.platformFee.toNumber())),
|
|
286
|
+
baseFee: Number((0, core_utils_1.bpsToPercent)(configInfo.baseFee.toNumber())),
|
|
287
|
+
frequencies: configInfo.frequencies.map((frequency) => frequency.toNumber()),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
async getStreamMetadataInfo(streamMetadata, commitment) {
|
|
291
|
+
const metadataInfo = await this.program.account.paymentStream.fetch((0, anchor_1.translateAddress)(streamMetadata), commitment ?? this.connection.commitment);
|
|
292
|
+
const streamToken = metadataInfo.financials.streamToken;
|
|
293
|
+
const streamTokenDecimals = await (0, solana_common_1.getMintDecimals)(this.connection, streamToken);
|
|
294
|
+
const unitsPerStreamToken = solana_common_1.TEN_BIGNUM.pow(streamTokenDecimals);
|
|
295
|
+
const depositedAmount = (0, bignumber_js_1.BigNumber)(metadataInfo.financials.depositedAmount.toString())
|
|
296
|
+
.div(unitsPerStreamToken)
|
|
297
|
+
.toFixed();
|
|
298
|
+
const withdrawnAmount = (0, bignumber_js_1.BigNumber)(metadataInfo.financials.withdrawnAmount.toString())
|
|
299
|
+
.div(unitsPerStreamToken)
|
|
300
|
+
.toFixed();
|
|
301
|
+
const cliffPercentage = Number((0, core_utils_1.bpsToPercent)(metadataInfo.financials.cliffPercentage.toNumber()));
|
|
302
|
+
return {
|
|
303
|
+
parties: {
|
|
304
|
+
sender: metadataInfo.parties.sender,
|
|
305
|
+
receiver: metadataInfo.parties.receiver,
|
|
306
|
+
},
|
|
307
|
+
financials: {
|
|
308
|
+
streamToken,
|
|
309
|
+
cliffPercentage,
|
|
310
|
+
depositedAmount,
|
|
311
|
+
withdrawnAmount,
|
|
312
|
+
},
|
|
313
|
+
schedule: {
|
|
314
|
+
startTime: metadataInfo.schedule.startTime.toNumber(),
|
|
315
|
+
endTime: metadataInfo.schedule.endTime.toNumber(),
|
|
316
|
+
lastWithdrawTime: metadataInfo.schedule.lastWithdrawTime.toNumber(),
|
|
317
|
+
frequency: metadataInfo.schedule.frequency.toNumber(),
|
|
318
|
+
duration: metadataInfo.schedule.duration.toNumber(),
|
|
319
|
+
pausedTimestamp: metadataInfo.schedule.pausedTimestamp.toNumber(),
|
|
320
|
+
pausedInterval: metadataInfo.schedule.pausedInterval.toNumber(),
|
|
321
|
+
canceledTimestamp: metadataInfo.schedule.canceledTimestamp.toNumber(),
|
|
322
|
+
},
|
|
323
|
+
permissions: {
|
|
324
|
+
cancelableBySender: Boolean(metadataInfo.permissions.cancelableBySender),
|
|
325
|
+
cancelableByRecipient: Boolean(metadataInfo.permissions.cancelableBySender),
|
|
326
|
+
automaticWithdrawal: Boolean(metadataInfo.permissions.automaticWithdrawal),
|
|
327
|
+
transferableBySender: Boolean(metadataInfo.permissions.transferableBySender),
|
|
328
|
+
transferableByRecipient: Boolean(metadataInfo.permissions.transferableByRecipient),
|
|
329
|
+
canTopup: Boolean(metadataInfo.permissions.canTopup),
|
|
330
|
+
isPausable: Boolean(metadataInfo.permissions.isPausable),
|
|
331
|
+
rateUpdatable: Boolean(metadataInfo.permissions.rateUpdatable),
|
|
332
|
+
},
|
|
333
|
+
streamName: anchor_1.utils.bytes.utf8.decode(Uint8Array.from(metadataInfo.streamName)),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
exports.ZebecStreamService = ZebecStreamService;
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { PublicKey } from "@solana/web3.js";
|
|
2
|
+
export type Numeric = string | number;
|
|
3
|
+
export type StreamConfigInfo = {
|
|
4
|
+
admin: PublicKey;
|
|
5
|
+
withdrawerAccount: PublicKey;
|
|
6
|
+
whitelistedTokens: PublicKey[];
|
|
7
|
+
platformFee: number;
|
|
8
|
+
baseFee: number;
|
|
9
|
+
frequencies: number[];
|
|
10
|
+
};
|
|
11
|
+
export type StreamMetadataInfo = {
|
|
12
|
+
parties: {
|
|
13
|
+
sender: PublicKey;
|
|
14
|
+
receiver: PublicKey;
|
|
15
|
+
};
|
|
16
|
+
financials: {
|
|
17
|
+
streamToken: PublicKey;
|
|
18
|
+
cliffPercentage: number;
|
|
19
|
+
depositedAmount: string;
|
|
20
|
+
withdrawnAmount: string;
|
|
21
|
+
};
|
|
22
|
+
schedule: {
|
|
23
|
+
startTime: number;
|
|
24
|
+
endTime: number;
|
|
25
|
+
lastWithdrawTime: number;
|
|
26
|
+
frequency: number;
|
|
27
|
+
duration: number;
|
|
28
|
+
pausedTimestamp: number;
|
|
29
|
+
pausedInterval: number;
|
|
30
|
+
canceledTimestamp: number;
|
|
31
|
+
};
|
|
32
|
+
permissions: {
|
|
33
|
+
cancelableBySender: boolean;
|
|
34
|
+
cancelableByRecipient: boolean;
|
|
35
|
+
automaticWithdrawal: boolean;
|
|
36
|
+
transferableBySender: boolean;
|
|
37
|
+
transferableByRecipient: boolean;
|
|
38
|
+
canTopup: boolean;
|
|
39
|
+
isPausable: boolean;
|
|
40
|
+
rateUpdatable: boolean;
|
|
41
|
+
};
|
|
42
|
+
streamName: string;
|
|
43
|
+
};
|
package/dist/types.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zebec-network/zebec-stream-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "This is an SDK for interacting with ZEBEC Stream Program in solana",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"author": "Ashish Sapkota",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "npm run clean && tsc",
|
|
14
|
+
"clean": "rimraf ./dist",
|
|
15
|
+
"format": "prettier --write .",
|
|
16
|
+
"start": "ts-node src/index.ts",
|
|
17
|
+
"test": "ts-mocha -p ./tsconfig.json -t 1000000000 test/**/*.spec.ts",
|
|
18
|
+
"test:single": "ts-mocha -p ./tsconfig.json -t 1000000000"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@solana/spl-token": "^0.4.13",
|
|
22
|
+
"@types/mocha": "^10.0.10",
|
|
23
|
+
"@types/node": "^24.0.15",
|
|
24
|
+
"dotenv": "^17.2.0",
|
|
25
|
+
"mocha": "^11.7.1",
|
|
26
|
+
"prettier": "^3.6.2",
|
|
27
|
+
"rimraf": "^6.0.1",
|
|
28
|
+
"ts-mocha": "^11.1.0",
|
|
29
|
+
"ts-node": "^10.9.2",
|
|
30
|
+
"typescript": "^5.8.3"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@coral-xyz/anchor": "^0.31.1",
|
|
34
|
+
"@solana/web3.js": "^1.98.2",
|
|
35
|
+
"@types/bn.js": "^5.2.0",
|
|
36
|
+
"@zebec-network/core-utils": "^1.0.4",
|
|
37
|
+
"@zebec-network/solana-common": "^1.5.1",
|
|
38
|
+
"bignumber.js": "^9.3.1"
|
|
39
|
+
}
|
|
40
|
+
}
|