Skip to content

Commit 22bb18c

Browse files
authored
Merge pull request #266 from streamflow-finance/feat/add-custom-instructions-on-top-of-stream-generation
7.4.8: Add support for custom transaction instructions in Solana stream client
2 parents 5470871 + 7de6677 commit 22bb18c

File tree

10 files changed

+78
-23
lines changed

10 files changed

+78
-23
lines changed

lerna.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
"packages": [
33
"packages/*"
44
],
5-
"version": "7.4.7",
5+
"version": "7.4.8",
66
"$schema": "node_modules/lerna/schemas/lerna-schema.json"
77
}

packages/common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/common",
3-
"version": "7.4.7",
3+
"version": "7.4.8",
44
"description": "Common utilities and types used by streamflow packages.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "./dist/esm/index.js",

packages/distributor/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/distributor",
3-
"version": "7.4.7",
3+
"version": "7.4.8",
44
"description": "JavaScript SDK to interact with Streamflow Airdrop protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "dist/esm/index.js",

packages/eslint-config/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/eslint-config",
3-
"version": "7.4.7",
3+
"version": "7.4.8",
44
"license": "ISC",
55
"main": "index.js",
66
"files": [

packages/launchpad/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/launchpad",
3-
"version": "7.4.7",
3+
"version": "7.4.8",
44
"description": "JavaScript SDK to interact with Streamflow Launchpad protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "dist/esm/index.js",

packages/staking/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/staking",
3-
"version": "7.4.7",
3+
"version": "7.4.8",
44
"description": "JavaScript SDK to interact with Streamflow Staking protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "dist/esm/index.js",

packages/stream/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@streamflow/stream",
3-
"version": "7.4.7",
3+
"version": "7.4.8",
44
"description": "JavaScript SDK to interact with Streamflow protocol.",
55
"homepage": "https://github.com/streamflow-finance/js-sdk/",
66
"main": "./dist/esm/index.js",

packages/stream/solana/StreamClient.ts

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
ICreateStreamSolanaExt,
4747
IInteractStreamSolanaExt,
4848
ITopUpStreamSolanaExt,
49+
ITransactionSolanaExtWithInstructions,
4950
ISearchStreams,
5051
ICreateStreamInstructions,
5152
AlignedContract,
@@ -111,7 +112,7 @@ import { BaseStreamClient } from "../common/BaseStreamClient.js";
111112
import { IPartnerLayout } from "./instructionTypes.js";
112113
import { calculateTotalAmountToDeposit } from "../common/utils.js";
113114
import { WITHDRAW_AVAILABLE_AMOUNT } from "../common/constants.js";
114-
import { StreamflowAlignedUnlocks as AlignedUnlocksProgramType } from "./descriptor/streamflow_aligned_unlocks";
115+
import { StreamflowAlignedUnlocks as AlignedUnlocksProgramType } from "./descriptor/streamflow_aligned_unlocks.js";
115116
import StreamflowAlignedUnlocksIDL from "./descriptor/idl/streamflow_aligned_unlocks.json";
116117
import { deriveContractPDA, deriveEscrowPDA, deriveTestOraclePDA } from "./lib/derive-accounts.js";
117118
import { isCreateAlignedStreamData } from "../common/contractUtils.js";
@@ -220,7 +221,7 @@ export class SolanaStreamClient extends BaseStreamClient {
220221
*/
221222
public async create(data: ICreateStreamData, extParams: ICreateStreamSolanaExt): Promise<ICreateResult> {
222223
const { partner, amount, tokenProgramId } = data;
223-
const { isNative, sender } = extParams;
224+
const { isNative, sender, customInstructions } = extParams;
224225

225226
const partnerPublicKey = partner ? new PublicKey(partner) : WITHDRAWOR_PUBLIC_KEY;
226227
const mintPublicKey = new PublicKey(data.tokenId);
@@ -229,7 +230,7 @@ export class SolanaStreamClient extends BaseStreamClient {
229230
throw new Error("Sender's PublicKey is not available, check passed wallet adapter!");
230231
}
231232

232-
const ixs = await this.getCreateATAInstructions(
233+
const ixs: TransactionInstruction[] = await this.getCreateATAInstructions(
233234
[STREAMFLOW_TREASURY_PUBLIC_KEY, partnerPublicKey],
234235
mintPublicKey,
235236
sender,
@@ -249,13 +250,9 @@ export class SolanaStreamClient extends BaseStreamClient {
249250
ixs.push(...(await prepareWrappedAccount(this.connection, sender.publicKey, totalAmount)));
250251
}
251252

252-
const { tx, hash, context } = await prepareTransaction(
253-
this.connection,
254-
ixs,
255-
extParams.sender.publicKey,
256-
undefined,
257-
metadata,
258-
);
253+
await this.applyCustomAfterInstructions(ixs, customInstructions, metadataPubKey);
254+
255+
const { tx, hash, context } = await prepareTransaction(this.connection, ixs, sender.publicKey, undefined, metadata);
259256
const signature = await signAndExecuteTransaction(
260257
this.connection,
261258
extParams.sender,
@@ -653,7 +650,14 @@ export class SolanaStreamClient extends BaseStreamClient {
653650
): Promise<IMultiTransactionResult> {
654651
const { recipients, ...streamParams } = data;
655652

656-
const { sender, metadataPubKeys: metadataPubKeysExt, isNative, computePrice, computeLimit } = extParams;
653+
const {
654+
sender,
655+
metadataPubKeys: metadataPubKeysExt,
656+
isNative,
657+
computePrice,
658+
computeLimit,
659+
customInstructions,
660+
} = extParams;
657661

658662
const metadatas: string[] = [];
659663
const metadataToRecipient: MetadataRecipientHashMap = {};
@@ -686,13 +690,15 @@ export class SolanaStreamClient extends BaseStreamClient {
686690
metadataPubKeys: metadataPubKeys[i] ? [metadataPubKeys[i]] : undefined,
687691
computePrice,
688692
computeLimit,
693+
customInstructions,
689694
};
690695

691696
const { ixs, metadata, metadataPubKey } = await this.prepareCreateInstructions(
692697
createStreamData,
693698
createStreamExtParams,
694699
);
695700

701+
await this.applyCustomAfterInstructions(ixs, customInstructions, metadataPubKey);
696702
metadataToRecipient[metadataPubKey.toBase58()] = recipientData;
697703

698704
metadatas.push(metadataPubKey.toBase58());
@@ -803,7 +809,14 @@ export class SolanaStreamClient extends BaseStreamClient {
803809
): Promise<IMultiTransactionResult> {
804810
const { recipients, ...streamParams } = data;
805811

806-
const { sender, metadataPubKeys: metadataPubKeysExt, isNative, computePrice, computeLimit } = extParams;
812+
const {
813+
sender,
814+
metadataPubKeys: metadataPubKeysExt,
815+
isNative,
816+
computePrice,
817+
computeLimit,
818+
customInstructions,
819+
} = extParams;
807820

808821
const metadatas: string[] = [];
809822
const metadataToRecipient: MetadataRecipientHashMap = {};
@@ -836,13 +849,15 @@ export class SolanaStreamClient extends BaseStreamClient {
836849
metadataPubKeys: metadataPubKeys[i] ? [metadataPubKeys[i]] : undefined,
837850
computePrice,
838851
computeLimit,
852+
customInstructions,
839853
};
840854

841855
const { ixs, metadata, metadataPubKey } = await this.prepareCreateInstructions(
842856
createStreamData,
843857
createStreamExtParams,
844858
);
845859

860+
await this.applyCustomAfterInstructions(ixs, customInstructions, metadataPubKey);
846861
metadataToRecipient[metadataPubKey.toBase58()] = recipientData;
847862

848863
metadatas.push(metadataPubKey.toBase58());
@@ -934,8 +949,18 @@ export class SolanaStreamClient extends BaseStreamClient {
934949
{ id, amount = WITHDRAW_AVAILABLE_AMOUNT }: IWithdrawData,
935950
extParams: IInteractStreamSolanaExt,
936951
): Promise<ITransactionResult> {
952+
const { invoker, customInstructions } = extParams;
953+
954+
if (!invoker.publicKey) {
955+
throw new Error("Invoker's PublicKey is not available, check passed wallet adapter!");
956+
}
957+
937958
const ixs: TransactionInstruction[] = await this.prepareWithdrawInstructions({ id, amount }, extParams);
938-
const { tx, hash, context } = await prepareTransaction(this.connection, ixs, extParams.invoker.publicKey);
959+
960+
const metadata = new PublicKey(id);
961+
await this.applyCustomAfterInstructions(ixs, customInstructions, metadata);
962+
963+
const { tx, hash, context } = await prepareTransaction(this.connection, ixs, invoker.publicKey);
939964
const signature = await signAndExecuteTransaction(
940965
this.connection,
941966
extParams.invoker,
@@ -1574,4 +1599,21 @@ export class SolanaStreamClient extends BaseStreamClient {
15741599
);
15751600
return checkOrCreateAtaBatch(this.connection, uniqueOwners, mint, invoker, programId);
15761601
}
1602+
1603+
private async applyCustomAfterInstructions(
1604+
ixs: TransactionInstruction[],
1605+
customInstructions: ITransactionSolanaExtWithInstructions["customInstructions"],
1606+
metadata?: PublicKey,
1607+
): Promise<void> {
1608+
if (customInstructions?.after) {
1609+
const afterInstructions =
1610+
typeof customInstructions.after === "function"
1611+
? await customInstructions.after({
1612+
instructions: ixs,
1613+
metadata,
1614+
})
1615+
: customInstructions.after;
1616+
ixs.push(...afterInstructions);
1617+
}
1618+
}
15771619
}

packages/stream/solana/lib/derive-accounts.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { PublicKey } from "@solana/web3.js";
22

3-
import { CONTRACT_SEED, ESCROW_SEED, TEST_ORACLE_SEED } from "../constants";
3+
import { CONTRACT_SEED, ESCROW_SEED, TEST_ORACLE_SEED } from "../constants.js";
44

55
export const deriveContractPDA = (programId: PublicKey, streamMetadata: PublicKey): PublicKey => {
66
return PublicKey.findProgramAddressSync([CONTRACT_SEED, streamMetadata.toBuffer()], programId)[0];

packages/stream/solana/types.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,19 @@ export interface ICreateSolanaExt {
4141
isNative?: boolean;
4242
}
4343

44-
export interface ICreateStreamSolanaExt extends ICreateSolanaExt, ITransactionSolanaExt {
44+
export interface ITransactionSolanaExtWithInstructions extends ITransactionSolanaExt {
45+
customInstructions?: {
46+
after?: InstructionGenerator;
47+
};
48+
}
49+
50+
export interface ICreateStreamSolanaExt extends ICreateSolanaExt, ITransactionSolanaExtWithInstructions {
4551
// allow custom Metadata Account to be passed, ephemeral signer is most cases, accepts array to be compatible in createMultiple
4652
metadataPubKeys?: PublicKey[];
4753
partner?: string | null;
4854
}
4955

50-
export interface IInteractStreamSolanaExt extends ITransactionSolanaExt {
56+
export interface IInteractStreamSolanaExt extends ITransactionSolanaExtWithInstructions {
5157
invoker: SignerWalletAdapter | Keypair;
5258
checkTokenAccounts?: boolean;
5359
}
@@ -307,3 +313,10 @@ export interface BatchItemError extends BatchItem {
307313
}
308314

309315
export type BatchItemResult = BatchItemSuccess | BatchItemError;
316+
317+
export type InstructionGenerator =
318+
| TransactionInstruction[]
319+
| ((params: {
320+
instructions: TransactionInstruction[];
321+
metadata?: PublicKey;
322+
}) => TransactionInstruction[] | Promise<TransactionInstruction[]>);

0 commit comments

Comments
 (0)