Tilaussuunnitelma mahdollistaa kauppiaan julkaista laskutusehdot, jotka käyttäjät voivat hyväksyä. Kun käyttäjä tilaa, kauppias tai hyväksytty noutaja voi periä enintään suunnitelman summan jokaiselta laskutusjaksolta.
Tämä opas esittää koko työnkulun rakennuspalikoina. Kauppias luo suunnitelman, tilaaja hyväksyy sen, ja kauppias tai noutaja kerää maksut tuloksena syntyneestä tilaus-PDA:sta.
Asennus
pnpm add @solana/subscriptions @solana/kit @solana/kit-plugin-rpc @solana/kit-plugin-signer @solana-program/token
Suunnitelman luominen
Kauppias omistaa suunnitelman. Suunnitelma-PDA johdetaan kauppiaan osoitteesta
ja planId.
Sponsori voi rahoittaa suunnitelman rent-maksun välittämällä valinnaisen payer-parametrin, jolloin kauppias säilyy suunnitelman omistajana. Suunnitelman poistaminen palauttaa maksun omistajalle, ei maksajalle, joten sponsorointi tulee rajoittaa ketjun ulkopuolisesti.
import { address, createClient } from '@solana/kit';import { solanaLocalRpc } from '@solana/kit-plugin-rpc';import { signer } from '@solana/kit-plugin-signer';import { findPlanPda, subscriptionsProgram } from '@solana/subscriptions';const merchantClient = createClient().use(signer(merchantSigner)).use(solanaLocalRpc({ rpcUrl: 'http://127.0.0.1:8899' })).use(subscriptionsProgram());const planId = 1n;const tokenMint = address('TOKEN_MINT_ADDRESS_HERE');const amount = 5_000_000n;const periodHours = 720n;const metadataUri = 'https://example.com/plan.json';const destinations = [merchantSigner.address];const pullers = [address('PULLER_WALLET_ADDRESS_HERE')];await merchantClient.subscriptions.instructions.createPlan({planId,mint: tokenMint,amount,periodHours,endTs: 0n,destinations,pullers,metadataUri,}).sendTransaction();const [planPda] = await findPlanPda({owner: merchantSigner.address,planId,});
Suunnitelman päivittäminen
Kauppias voi päivittää muokattavat suunnitelmakentät luomisen jälkeen. Olemassa olevat tilaajat pitävät hyväksymänsä ehdot, kun taas uudet tilaajat hyväksyvät nykyiset suunnitelman ehdot.
Muutama sääntö pätee:
- Rajallista
endTsvoidaan vain lyhentää, ei koskaan pidentää tai tyhjentää (PlanEndTsCannotExtend). Sunset-suunnitelmassa voit poistaa vetäjiä (uuden joukon on oltava nykyisen osajoukko) vaarantuneen vetäjän oikeuksien peruuttamiseksi; tila,endTsja metatiedot pysyvät muuttumattomina.- Muokkaukset toimivat suunnitelman viimeisen laskutuskauden aikana, kunhan
endTspysyy muuttumattomana. - Instruktiossa on allekirjoitushetkellä havaittu suunnitelman tila
(
expectedCreatedAt,expectedEndTs,expectedPullers,expectedMetadataUri). Jos live-suunnitelma ei enää vastaa tätä tilaa, päivitys hylätään (StalePlanApproval), joten vanhentunut allekirjoitettu päivitys ei voi palauttaa poistettuja pullereita tai kumota myöhempiä muokkauksia. LiitännäisasiakkaanupdatePlanhakee live-tilan puolestasi; kun rakennat manuaalisesti, hae suunnitelma ja välitä kentät itse.
import { PlanStatus } from '@solana/subscriptions';const updatedMetadataUri = 'https://example.com/updated-plan.json';const updatedPullers = [address('NEW_PULLER_WALLET_ADDRESS_HERE')];await merchantClient.subscriptions.instructions.updatePlan({owner: merchantSigner,planPda,status: PlanStatus.Active,endTs: 0n,pullers: updatedPullers,metadataUri: updatedMetadataUri,}).sendTransaction();
Tilaa
Tilaaja hyväksyy voimassa olevat suunnitelmaehdot. Tilauksen PDA johdetaan suunnitelman PDA:sta ja tilaajan osoitteesta.
Yhdistääksesi auktoriteetin alustuksen ja tilauksen yhdeksi transaktioksi, välitä
sentineliarvo UNKNOWN_INIT_ID (viety TypeScript SDK:sta)
expectedSubscriptionAuthorityInitId-parametrina. Ohjelma hyväksyy auktoriteetin
vain, jos se luotiin nykyisessä slot-yksikössä, joten sentineliarvo toimii uusille
rekisteröitymisille; palaavan käyttäjän, jonka auktoriteetti luotiin aiemmassa
slot-yksikössä, on välitettävä todellinen initId (liitännäisasiakas hakee sen
puolestasi) tai kutsu epäonnistuu virheellä StaleSubscriptionAuthority.
import { createClient } from '@solana/kit';import { solanaLocalRpc } from '@solana/kit-plugin-rpc';import { signer } from '@solana/kit-plugin-signer';import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';import {fetchMaybeSubscriptionAuthority,findSubscriptionAuthorityPda,findSubscriptionDelegationPda,subscriptionsProgram,} from '@solana/subscriptions';const subscriberClient = createClient().use(signer(subscriberSigner)).use(solanaLocalRpc({ rpcUrl: 'http://127.0.0.1:8899' })).use(subscriptionsProgram());const [subscriberAta] = await findAssociatedTokenPda({mint: tokenMint,owner: subscriberSigner.address,tokenProgram: TOKEN_PROGRAM_ADDRESS,});const [subscriptionAuthorityPda] = await findSubscriptionAuthorityPda({user: subscriberSigner.address,tokenMint,});const subscriptionAuthority = await fetchMaybeSubscriptionAuthority(subscriberClient.rpc,subscriptionAuthorityPda,);if (!subscriptionAuthority.exists) {await subscriberClient.subscriptions.instructions.initSubscriptionAuthority({tokenMint,tokenProgram: TOKEN_PROGRAM_ADDRESS,userAta: subscriberAta,}).sendTransaction();}await subscriberClient.subscriptions.instructions.subscribe({merchant: merchantSigner.address,planId,tokenMint,}).sendTransaction();const [subscriptionPda] = await findSubscriptionDelegationPda({planPda,subscriber: subscriberSigner.address,});
Kerää Maksu
Kauppias tai sallittu vetäjä allekirjoittaa keräyksen. Kun suunnitelma käyttää
kohteen sallittujen listaa, vastaanottajan token account -omistajan on oltava
merkittynä destinations:ssä.
const receiverAta = address('MERCHANT_TOKEN_ACCOUNT_ADDRESS_HERE');await merchantClient.subscriptions.instructions.transferSubscription({caller: merchantOrPullerSigner,delegator: subscriberSigner.address,tokenMint,subscriptionPda,planPda,amount: 200_000n,receiverAta,tokenProgram: TOKEN_PROGRAM_ADDRESS,}).sendTransaction();
Peruuta ja kumoa
Peruuttaminen merkitsee tilauksen päättyväksi. Kumoaminen sulkee tilauksen PDA:n, kun peruutuksen voimassaoloaika on kulunut. Tilaaja allekirjoittaa molemmat tapahtumat.
await subscriberClient.subscriptions.instructions.cancelSubscription({subscriber: subscriberSigner,planPda,subscriptionPda,}).sendTransaction();// Run this after the cancelled subscription's expiresAtTs has elapsed.await subscriberClient.subscriptions.instructions.revokeSubscription({authority: subscriberSigner,planPda,subscriptionPda,}).sendTransaction();
Peruuta välittömästi
Kun sekä tilaaja että nykyinen suunnitelman omistaja allekirjoittavat,
cancelSubscriptionNow asettaa tilauksen päättymään peruutushetkellä laskutuskauden
loppuun sijasta. Se voi myös lyhentää odottavaa lisäaikakauden peruutusta. Hyväksyntä
on sidottu allekirjoitushetkellä havaittuun kauden alkuun; jos tilaus on muuttunut
sen jälkeen, transaktio hylätään (StaleSubscriptionApproval).
import { fetchSubscriptionDelegation } from '@solana/subscriptions';const subscription = await fetchSubscriptionDelegation(subscriberClient.rpc,subscriptionPda,);await subscriberClient.subscriptions.instructions.cancelSubscriptionNow({subscriber: subscriberSigner,merchant: merchantSigner,planPda,expectedCurrentPeriodStartTs: subscription.data.currentPeriodStartTs,}).sendTransaction();
Jatka tilausta
Peruutetun tilauksen voi reaktivoida ennen sen kumoamista. Kun tilaus on
kumottu, tilaustilin tiedot suljetaan ja tilaajan täytyy
tilata uudelleen. Jatkaminen edellyttää tilaajan
SubscriptionAuthority suunnitelman minttiä varten, jonka ohjelma vahvistaa
(omistaja, mintti ja init_id) ja hylkää, jos se on vanhentunut tai uudelleen
alustettu.
Instruktiossa on tilaajan allekirjoitushetkellä havaitsema vanhentumisaika
(expectedExpiresAtTs); ristiriita hylätään (StaleSubscriptionApproval),
joten vanhentunut allekirjoitettu jatkaminen ei voi poistaa myöhempää peruutusta,
jota tilaaja ei ole hyväksynyt.
import { fetchSubscriptionDelegation } from '@solana/subscriptions';const subscription = await fetchSubscriptionDelegation(subscriberClient.rpc,subscriptionPda,);await subscriberClient.subscriptions.instructions.resumeSubscription({subscriber: subscriberSigner,planPda,tokenMint,expectedExpiresAtTs: subscription.data.expiresAtTs,}).sendTransaction();
Huomioita
amounton perusyksiköissä. 6 desimaalin tokenille5_000_000tarkoittaa5tokenia.- TypeScript SDK hakee reaaliaikaiset suunnitelman ehdot
subscribeaikana, kun jätät ne pois. - Rust
SubscribeBuildertarvitsee odotetut suunnitelman ehdot. Hae ja pura suunnitelmatili ensin, sitten välitä nämä kentätSubscribeDatakautta. - Vain kauppias tai
pullers-listalla oleva lompakko voi kerätä maksuja. - Tilaaja allekirjoittaa asennuksen, peruutuksen ja kumoamisen tapahtumat. Kauppias tai hyväksytty kerääjä allekirjoittaa maksutapahtumat.
Is this page helpful?