11import { DONATION_CONTRACT_ACCOUNT_ID } from "@/common/_config" ;
2- import { contractApi } from "@/common/blockchains/near-protocol/client" ;
2+ import { contractApi , walletApi } from "@/common/blockchains/near-protocol/client" ;
33import { FULL_TGAS } from "@/common/constants" ;
44import type { IndivisibleUnits } from "@/common/types" ;
55
@@ -10,6 +10,11 @@ import {
1010 DirectDonationConfig ,
1111} from "./interfaces" ;
1212
13+ export type DirectDonateResult = {
14+ donation : DirectDonation ;
15+ txHash : string | null ;
16+ } ;
17+
1318const donationContractApi = contractApi ( {
1419 contractId : DONATION_CONTRACT_ACCOUNT_ID ,
1520} ) ;
@@ -41,25 +46,145 @@ export const get_donations_for_donor = (args: { donor_id: string }) =>
4146 args,
4247 } ) ;
4348
44- export const donate = ( args : DirectDonationArgs , depositAmountYocto : IndivisibleUnits ) =>
45- donationContractApi . call < typeof args , DirectDonation > ( "donate" , {
49+ export const donate = async (
50+ args : DirectDonationArgs ,
51+ depositAmountYocto : IndivisibleUnits ,
52+ ) : Promise < DirectDonateResult > => {
53+ const wallet = await walletApi . ensureWallet ( ) ;
54+ const signerId = walletApi . accountId ;
55+
56+ if ( ! signerId ) {
57+ throw new Error ( "Wallet is not signed in." ) ;
58+ }
59+
60+ const { actionCreators } = await import ( "@near-js/transactions" ) ;
61+ const { providers } = await import ( "near-api-js" ) ;
62+
63+ const action = actionCreators . functionCall (
64+ "donate" ,
4665 args ,
47- deposit : depositAmountYocto ,
48- gas : FULL_TGAS ,
49- callbackUrl : window . location . href ,
50- } ) ;
66+ BigInt ( FULL_TGAS ) ,
67+ BigInt ( depositAmountYocto ) ,
68+ ) ;
69+
70+ let outcome : any ;
71+ const walletAny = wallet as any ;
72+
73+ if ( "signAndSendTransaction" in walletAny ) {
74+ outcome = await walletAny . signAndSendTransaction ( {
75+ signerId,
76+ receiverId : DONATION_CONTRACT_ACCOUNT_ID ,
77+ actions : [ action ] ,
78+ } ) ;
79+ } else if ( "signAndSendTransactions" in walletAny ) {
80+ const results = await walletAny . signAndSendTransactions ( {
81+ transactions : [
82+ {
83+ receiverId : DONATION_CONTRACT_ACCOUNT_ID ,
84+ actions : [ action ] ,
85+ } ,
86+ ] ,
87+ } ) ;
88+
89+ outcome = Array . isArray ( results ) ? results [ 0 ] : results ;
90+ } else {
91+ throw new Error ( "Wallet does not support transaction signing" ) ;
92+ }
93+
94+ const txHash = outcome ?. transaction ?. hash || outcome ?. transaction_outcome ?. id || null ;
95+ const donation = providers . getTransactionLastResult ( outcome ) as DirectDonation ;
96+
97+ return { donation, txHash } ;
98+ } ;
99+
100+ export type DirectBatchDonateResult = {
101+ donations : DirectDonation [ ] ;
102+ txHash : string | null ;
103+ } ;
51104
52- export const donateBatch = ( txInputs : DirectBatchDonationItem [ ] ) =>
53- donationContractApi . callMultiple < DirectDonationArgs > (
54- txInputs . map ( ( { amountYoctoNear, ...txInput } ) => ( {
55- method : "donate" ,
56- deposit : amountYoctoNear ,
57- gas : FULL_TGAS ,
105+ export const donateBatch = async (
106+ txInputs : DirectBatchDonationItem [ ] ,
107+ ) : Promise < DirectBatchDonateResult > => {
108+ const wallet = await walletApi . ensureWallet ( ) ;
109+ const signerId = walletApi . accountId ;
58110
59- ...txInput ,
60- } ) ) ,
111+ if ( ! signerId ) {
112+ throw new Error ( "Wallet is not signed in." ) ;
113+ }
114+
115+ const { actionCreators } = await import ( "@near-js/transactions" ) ;
116+ const { providers } = await import ( "near-api-js" ) ;
117+
118+ // Create actions for each donation
119+ const actions = txInputs . map ( ( { amountYoctoNear, args } ) =>
120+ actionCreators . functionCall ( "donate" , args , BigInt ( FULL_TGAS ) , BigInt ( amountYoctoNear ) ) ,
61121 ) ;
62122
123+ let outcome : any ;
124+ const walletAny = wallet as any ;
125+
126+ if ( "signAndSendTransaction" in walletAny ) {
127+ // Single transaction with multiple actions
128+ outcome = await walletAny . signAndSendTransaction ( {
129+ signerId,
130+ receiverId : DONATION_CONTRACT_ACCOUNT_ID ,
131+ actions,
132+ } ) ;
133+ } else if ( "signAndSendTransactions" in walletAny ) {
134+ // For wallets that only support signAndSendTransactions
135+ const results = await walletAny . signAndSendTransactions ( {
136+ transactions : [
137+ {
138+ receiverId : DONATION_CONTRACT_ACCOUNT_ID ,
139+ actions,
140+ } ,
141+ ] ,
142+ } ) ;
143+
144+ outcome = Array . isArray ( results ) ? results [ 0 ] : results ;
145+ } else {
146+ throw new Error ( "Wallet does not support transaction signing" ) ;
147+ }
148+
149+ const txHash = outcome ?. transaction ?. hash || outcome ?. transaction_outcome ?. id || null ;
150+
151+ // Parse all donations from the outcome
152+ const donations : DirectDonation [ ] = [ ] ;
153+
154+ if ( outcome ?. receipts_outcome ) {
155+ for ( const receipt of outcome . receipts_outcome ) {
156+ const successValue = receipt ?. outcome ?. status ?. SuccessValue ;
157+
158+ if ( successValue ) {
159+ try {
160+ const parsed = JSON . parse ( atob ( successValue ) ) ;
161+
162+ if ( parsed && "recipient_id" in parsed && "donor_id" in parsed ) {
163+ donations . push ( parsed as DirectDonation ) ;
164+ }
165+ } catch {
166+ // Not valid JSON, skip
167+ }
168+ }
169+ }
170+ }
171+
172+ // Fallback: try to get last result
173+ if ( donations . length === 0 ) {
174+ try {
175+ const lastResult = providers . getTransactionLastResult ( outcome ) ;
176+
177+ if ( lastResult && typeof lastResult === "object" && "recipient_id" in lastResult ) {
178+ donations . push ( lastResult as DirectDonation ) ;
179+ }
180+ } catch {
181+ // Ignore
182+ }
183+ }
184+
185+ return { donations, txHash } ;
186+ } ;
187+
63188export const storage_deposit = ( depositAmountYocto : IndivisibleUnits ) =>
64189 donationContractApi . call < { } , IndivisibleUnits > ( "storage_deposit" , {
65190 deposit : depositAmountYocto ,
0 commit comments