-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmint.pact
298 lines (253 loc) · 8.31 KB
/
mint.pact
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
(namespace "free")
(define-keyset "free.kai-mint-gov" (read-keyset "kai-mint-gov"))
(define-keyset "free.kai-mint-bank" (read-keyset "kai-mint-bank"))
(module kai-mint GOV
(defcap GOV ()
(enforce-guard (keyset-ref-guard "free.kai-mint-gov" ))
)
(defcap MINTPROCESS ()
true
)
(use marmalade-v2.ledger)
; Lets revisit to make sure this can handle off chain onboarding
; of payments with stripe or other processors.
(defschema pay-schema
id:string
payer:string
payerGuard:guard
amount:decimal
fungible:module{fungible-v2}
minted:bool
)
(deftable payments:{pay-schema})
; Sale Process
(defcap PAYCAP:bool
(payment-id:string payer:string amount:decimal sale-id:string)
@doc "Wrapper cap/event of SALE for event processing"
@event
(enforce (> amount 0.0) "Amount must be positive")
(compose-capability (SENDPAY payment-id payer amount))
)
(defcap SENDPAY:bool
(payment-id:string payer:string amount:decimal)
@doc "Managed cap for PAYER to store mint funds."
@managed
; Do we need an enforce in here? I think we do
(compose-capability (DEBIT payer))
(compose-capability (CREDIT (escrow)))
)
(defun account-guard:guard (account:string)
@doc "Retrieves the guard associated with the given account."
(let* ((details (coin.details account))
(guard (at "guard" details)))
guard
)
)
(defun pay:bool (pay-data:object)
@doc "Create a new payment for minting"
(let* (
(payer:string (at "payer" pay-data))
(payerGuard:guard (at "payerGuard" pay-data))
(amount:decimal (at "amount" pay-data))
(fungible:module{fungible-v2} (at "fungible" pay-data))
(date:time (curr-time))
(id:string (hash {'payer:payer, 'amount:amount, 'date:date, 'guard:payerGuard}))
(bank:string (get-bank))
)
(enforce (= coin fungible)false)
(fungible::transfer payer bank amount)
; we need to add the contract to repl for zusd, replace second coin
(insert payments id {
'id: id,
'payer: payer,
'payerGuard: payerGuard,
'amount: amount,
'fungible: fungible,
'minted: false
} )
)
true
)
; We will need to compartmentalize the information in here and figure out a clean
; method to take a payment, record the successful state for minting, and handle
; return or release of payments from the escrow. Placeholders for now
; (defpact run-payment:bool (pay-data:object mint-data:object)
; (step-with-rollback
; ;; Step 1: Send a payment to escrow
; (pay pay-data)
; "yay"
; )
; (step
; ;; Step 1: Mint the NFT
; "yay"
; )
; )
(defpact run-payment:bool (pay-data:object)
@doc "Handles the payment and minting process in sequential steps."
(step-with-rollback
(let* (
(payment-id:string (pay pay-data))
(payment-record (get-payment-info payment-id))
(valid-payment (validate-payment payment-record))
)
(enforce valid-payment "Payment validation failed.")
(with-capability (SALE payment-id (at "payer" pay-data) (at "amount" pay-data) (pact-id))
(transfer-to-escrow payment-record)) ; Function to handle transfer to escrow
payment-id ; Continue with payment-id for next step
)
(let ((payment-record (get-payment-info (resume))))
(refund-payment payment-record)) ; Function to handle refund in case of rollback
)
(step
; We should consider storing these details in a table vs this approach. We can store it
; In our real time operations database as well, try what is faster imo.
(let* (
(payment-id:string (resume))
(mint-data:object (read-msg "mint-data"))
(mint-success:bool (create-marmalade-token mint-data payment-id))
)
(enforce mint-success "Minting of NFT failed.")
(release-funds-from-escrow payment-id) ; Function to handle fund release from escrow
"Minting successful"
)
)
)
; ---------------------- for step 1 in case we need it--------------------
;(token-id:string (at "token-id" mint-data))
;(uri:string (at "uri" mint-data))
;(policies (at "policies" mint-data))
;(pay-guard:guard (at "pay-guard" mint-data))
;(precision:integer 0)
;(mint-to-account:string (at "mint-to-account" mint-data))
;(mint-to-guard:guard (at "guard" (coin.details mint-to-account)))
;(new-token-id:string (create-token-id {'precision:precision, 'policies: policies, 'uri:uri} pay-guard))
;-------------------------------------------------------------------------
; Mint Functions
; Lets modify this further so it works for us
(defun create-marmalade-token:string
(
mint-data:object
id:string
)
@doc "Requires mint cap. Creates the token on marmalade using the supplied data"
; We can craft a new cap for this, just pass true for now
(with-capability (MINTPROCESS)
(with-read payments id
{
"id":= id
, "minted":= minted
}
(enforce (= minted false)
"Can't mint this token more than once"
)
(let*
(
(token-id:string (at "token-id" mint-data))
(uri:string (at "uri" mint-data))
(policies (at "policies" mint-data))
(guard:guard (at "pay-guard" mint-data))
(precision 0)
(mint-to-account:string (at "mint-to-account" mint-data))
(mint-to-guard:guard (at "guard" (coin.details mint-to-account)))
(token-id:string (create-token-id {'precision:precision, 'policies: policies, 'uri:uri} guard))
)
; This is required to create an actual NFT Token
(create-token
token-id
precision
uri
policies
guard
)
; This is where the actual NFT is minted on the ledger.
(mint
token-id
mint-to-account
mint-to-guard
1.0
)
(update payments id
{ "minted": true }
)
; Should we create this table structure?
; (insert nft-table token-id
; {
; "id": token-id,
; "owner": account
; }
; )
token-id
)
)
)
)
; Utility functions
(defun get-payment-info:object{pay-schema} (payment-id:string)
@doc "Retrieves payment information based on the payment ID."
(read payments payment-id)
)
(defun validate-payment:bool (payment-record:object{pay-schema})
@doc "Validates the payment details."
(and (not (= payment-record {})) ; Check if payment record is not empty
(not (at 'minted payment-record))) ; Ensure the payment has not been used for minting yet
)
(defun transfer-to-escrow:bool (payment-record:object{pay-schema})
@doc "Transfers funds to the escrow account."
; (transfer payer (escrow) amount)
; Implement logic to transfer funds to the escrow account
true ; Placeholder return value
)
(defun refund-payment:bool (payment-record:object{pay-schema})
@doc "Handles refund in case of rollback."
; Implement our logic to refund payment
true ; Placeholder return value
)
(defun release-funds-from-escrow:bool (payment-id:string)
@doc "Handles fund release from escrow upon successful minting."
; Implement our logic to release funds from escrow
true ; Placeholder return value
)
; Escrow functions
(defcap ESCROW ()
true)
(defun escrow-guard:guard ()
@doc "Return the guard of the escrow account"
(create-capability-pact-guard (ESCROW)))
(defun escrow:string ()
@doc "Return the escrow account"
(create-principal (escrow-guard)))
(defun curr-time:time ()
@doc "Returns current chain's block-time"
(at 'block-time (chain-data))
)
; Bank Info
(defschema bank-info
@doc "Stores string values"
value:string
)
(deftable bankInfo:{bank-info})
(defun update-bank (bankId:string value:string)
@doc "Updates the account for the bank"
(with-capability (GOV)
(write bankInfo bankId
{ "value": value }
)
)
)
(defun get-bank-value:string (bankId:string)
@doc "Gets the value with the provided id"
(at "value" (read bankInfo bankId ["value"]))
)
(defconst BANK_ACCOUNT:string "BANK")
(defun get-bank:string ()
(get-bank-value BANK_ACCOUNT)
)
(defun get ()
(select payments (constantly true)))
)
(if (read-msg "upgrade")
"Upgrade Complete"
[
(create-table payments)
(create-table bankInfo)
])