@meshsdk/contract 1.6.0-alpha.11

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.
Files changed (73) hide show
  1. package/README.md +5 -0
  2. package/package.json +37 -0
  3. package/src/common.ts +186 -0
  4. package/src/coupon-bond-guaranteed/aiken-workspace/readme.md +0 -0
  5. package/src/coupon-bond-guaranteed/offchain.ts +3 -0
  6. package/src/coupon-bond-guaranteed/readme.md +3 -0
  7. package/src/escrow/aiken-workspace/aiken.lock +26 -0
  8. package/src/escrow/aiken-workspace/aiken.toml +19 -0
  9. package/src/escrow/aiken-workspace/lib/escrow/types.ak +21 -0
  10. package/src/escrow/aiken-workspace/lib/escrow/validators/escrow.ak +122 -0
  11. package/src/escrow/aiken-workspace/plutus.json +238 -0
  12. package/src/escrow/aiken-workspace/readme.md +55 -0
  13. package/src/escrow/aiken-workspace/validators/escrow.ak +9 -0
  14. package/src/escrow/aiken-workspace/validators/tests/escrow.ak +462 -0
  15. package/src/escrow/index.ts +1 -0
  16. package/src/escrow/offchain.ts +254 -0
  17. package/src/escrow/readme.md +38 -0
  18. package/src/giftcard/aiken-workspace/aiken.lock +26 -0
  19. package/src/giftcard/aiken-workspace/aiken.toml +19 -0
  20. package/src/giftcard/aiken-workspace/plutus.json +138 -0
  21. package/src/giftcard/aiken-workspace/readme.md +55 -0
  22. package/src/giftcard/aiken-workspace/validators/oneshot.ak +173 -0
  23. package/src/giftcard/index.ts +1 -0
  24. package/src/giftcard/offchain.ts +184 -0
  25. package/src/giftcard/readme.md +36 -0
  26. package/src/hello-world/aiken-workspace/README.md +19 -0
  27. package/src/hello-world/aiken-workspace/aiken.lock +15 -0
  28. package/src/hello-world/aiken-workspace/aiken.toml +14 -0
  29. package/src/hello-world/aiken-workspace/contract.md +27 -0
  30. package/src/hello-world/aiken-workspace/plutus.json +69 -0
  31. package/src/hello-world/aiken-workspace/validators/hello_world.ak +24 -0
  32. package/src/hello-world/index.ts +1 -0
  33. package/src/hello-world/offchain.ts +24 -0
  34. package/src/hello-world/readme.md +1 -0
  35. package/src/index.ts +6 -0
  36. package/src/marketplace/aiken-workspace/aiken.lock +26 -0
  37. package/src/marketplace/aiken-workspace/aiken.toml +19 -0
  38. package/src/marketplace/aiken-workspace/lib/marketplace/types.ak +15 -0
  39. package/src/marketplace/aiken-workspace/lib/marketplace/validators/marketplace.ak +52 -0
  40. package/src/marketplace/aiken-workspace/plutus.json +204 -0
  41. package/src/marketplace/aiken-workspace/readme.md +55 -0
  42. package/src/marketplace/aiken-workspace/validators/marketplace.ak +14 -0
  43. package/src/marketplace/aiken-workspace/validators/tests/marketplace.ak +218 -0
  44. package/src/marketplace/index.ts +1 -0
  45. package/src/marketplace/offchain.ts +248 -0
  46. package/src/marketplace/readme.md +45 -0
  47. package/src/payment-splitter/aiken-workspace/aiken.lock +15 -0
  48. package/src/payment-splitter/aiken-workspace/aiken.toml +14 -0
  49. package/src/payment-splitter/aiken-workspace/plutus.json +83 -0
  50. package/src/payment-splitter/aiken-workspace/validators/payment-splitter.ak +329 -0
  51. package/src/payment-splitter/index.ts +1 -0
  52. package/src/payment-splitter/offchain.ts +143 -0
  53. package/src/payment-splitter/readme.md +100 -0
  54. package/src/swap/aiken-workspace/aiken.lock +26 -0
  55. package/src/swap/aiken-workspace/aiken.toml +19 -0
  56. package/src/swap/aiken-workspace/plutus.json +208 -0
  57. package/src/swap/aiken-workspace/readme.md +55 -0
  58. package/src/swap/aiken-workspace/validators/swap.ak +188 -0
  59. package/src/swap/index.ts +1 -0
  60. package/src/swap/offchain.ts +139 -0
  61. package/src/swap/readme.md +35 -0
  62. package/src/vesting/aiken-workspace/README.md +24 -0
  63. package/src/vesting/aiken-workspace/aiken.lock +26 -0
  64. package/src/vesting/aiken-workspace/aiken.toml +19 -0
  65. package/src/vesting/aiken-workspace/lib/vesting/types.ak +8 -0
  66. package/src/vesting/aiken-workspace/lib/vesting/validators/vesting.ak +19 -0
  67. package/src/vesting/aiken-workspace/plutus.json +67 -0
  68. package/src/vesting/aiken-workspace/validators/tests/vesting.ak +108 -0
  69. package/src/vesting/aiken-workspace/validators/vesting.ak +9 -0
  70. package/src/vesting/index.ts +1 -0
  71. package/src/vesting/offchain.ts +117 -0
  72. package/src/vesting/readme.md +36 -0
  73. package/tsconfig.json +5 -0
@@ -0,0 +1,208 @@
1
+ {
2
+ "preamble": {
3
+ "title": "meshjs/swap",
4
+ "description": "Aiken contracts for project 'meshjs/swap'",
5
+ "version": "0.0.0",
6
+ "plutusVersion": "v2",
7
+ "compiler": {
8
+ "name": "Aiken",
9
+ "version": "v1.0.24-alpha+982eff4"
10
+ },
11
+ "license": "Apache-2.0"
12
+ },
13
+ "validators": [
14
+ {
15
+ "title": "swap.swap",
16
+ "datum": {
17
+ "title": "datum",
18
+ "schema": {
19
+ "$ref": "#/definitions/swap~1SwapDatum"
20
+ }
21
+ },
22
+ "redeemer": {
23
+ "title": "redeemer",
24
+ "schema": {
25
+ "$ref": "#/definitions/swap~1SwapRedeemer"
26
+ }
27
+ },
28
+ "compiledCode": "59077601000032323232323232323222232325333008323232533300b3370e9001000899191919299980799b87480080084c94ccc040cdc3a4000601e0022646464646464646464646464a666038a6660380102002294040085281980299980200425eb7bdb180894ccc074cdd79807980d980a980d8010058998020009bab3015301b3015301b002100137566026603203066008664466600a00497adef6c6022533301e3375e6020603800400626600a0026eacc058c0700084004dd61802980c1806180c00a9806180c00b9bab30053018017223233300100100300222253330210021001132333004004302500333223233001001005225333026001133027337606ea4010dd3001a5eb7bdb1804c8c8c8c94ccc09ccdd799807804001260103d879800013302b337606ea4020dd30038028a99981399b8f0080021323253330293370e900000089981699bb03752014605c604e00400a200a604e00264a666050a66605600229445280a60103d87a800013374a9000198161ba60014bd70191998008008040011112999816801080089919980200218188019991191980080080291299981900089981999bb037520086ea000d2f5bded8c0264646464a66606666ebccc06c020009300103d8798000133037337606ea4020dd40038028a99981999b8f0080021323253330353370e900000089981c99bb037520146074606600400a200a606600264a66606866e1c005200014c103d87a800013374a90001981c1ba80014bd7019b80007001133037337606ea4008dd4000998030030019bad3034003375c6064004606c00460680026eb8c0b0004dd69816800981780109981599bb037520046e98004cc01801800cdd598140019bae3026002302a0023028001375c60400026eacc084004c08c008894ccc068cdc80010008a6103d87980001533301a3371e0040022980103d87a800014c103d87b8000222323300100100422533301f001100413300330210013300200230220012232323300100100222533301e00114a226464a66603a66e24dd698040011991191919299981119b8748008004520001375a604e6040004604000264a66604266e1d200200114c0103d87a8000132323300100100222533302700114c103d87a800013232323253330283371e014004266e9520003302c375000297ae0133006006003375a60520066eb8c09c008c0ac008c0a4004dd59813180f801180f80099198008008051129998120008a6103d87a800013232323253330253371e010004266e95200033029374c00297ae01330060060033756604c0066eb8c090008c0a0008c098004dd718078011bae301500213300400400114a060440046eb0c080004c8cc004004008894ccc07400452f5c0264666444646600200200644a66604600220062646604a6e9ccc094dd4803198129ba9375c60440026604a6ea0dd69811800a5eb80cc00c00cc09c008c094004dd7180e0009bab301d001330030033021002301f0012301b301c301c001533301700114a0264a6660300022944528180d00099191980080080111299980c8008a5eb804c8c94ccc060cdd79805180b1808180b00100309980e00119802002000899802002000980e801180d8009bac300530113005301100e30043010300a30100013016001300e0011632323300100100222533301500114c0103d87a80001323253330143375e600c6024004010266e952000330180024bd70099802002000980c801180b8009bac3001300d3001300d00a13232323300100100322533301600114a026464a66602a66e3c008014528899802002000980d0011bae3018001323253330123370e9000180880089bae30173010001163003300f0013002300e00d37586028602a602a602a602a602a602a602a602a601a6002601a014460280026018012602200260120042940c024004c004c01c0108c038c03c004526136563253330083370e90000008a99980598030020a4c2c2a66601066e1d20020011533300b300600414985858c01800cc8c8c94ccc024cdc3a40000022646464646464a666024602a0042646464931980500191919198068009191bad3018002375c602c0026eacc054008dd718098009980480211919198060009191bad3017002375c602a0026eacc050008dd7180900099299980819b87480000044c8c8c8c94ccc05cc0680084c8c9263253330163370e900000089919299980d980f00109924c64a66603266e1d200000113232533301e3021002132498c05400458c07c004c05c00854ccc064cdc3a40040022646464646464a666044604a0042930b1bad30230013023002375a604200260420046eb4c07c004c05c00858c05c00458c070004c05000c54ccc058cdc3a40040022a66603260280062930b0b180a00118070018b180c000980c001180b00098070030b18070028b1bab30130013013002375660220026022004601e002600e00c2c600e00a44646600200200644a66601c00229309919801801980900118019808000919299980419b87480000044c8c94ccc034c04000852616375c601c002600c0042a66601066e1d200200113232533300d3010002149858dd7180700098030010b1803000918029baa001230033754002ae6955ceaab9e5573eae815d0aba21",
29
+ "hash": "3f1869e426f5350c595ffd8ca4a6fba8186947ae0cd6c136fe23054a"
30
+ }
31
+ ],
32
+ "definitions": {
33
+ "ByteArray": {
34
+ "dataType": "bytes"
35
+ },
36
+ "Int": {
37
+ "dataType": "integer"
38
+ },
39
+ "Option$aiken/transaction/credential/Referenced$aiken/transaction/credential/Credential": {
40
+ "title": "Optional",
41
+ "anyOf": [
42
+ {
43
+ "title": "Some",
44
+ "description": "An optional value.",
45
+ "dataType": "constructor",
46
+ "index": 0,
47
+ "fields": [
48
+ {
49
+ "$ref": "#/definitions/aiken~1transaction~1credential~1Referenced$aiken~1transaction~1credential~1Credential"
50
+ }
51
+ ]
52
+ },
53
+ {
54
+ "title": "None",
55
+ "description": "Nothing.",
56
+ "dataType": "constructor",
57
+ "index": 1,
58
+ "fields": []
59
+ }
60
+ ]
61
+ },
62
+ "aiken/dict/Dict$ByteArray_Int": {
63
+ "title": "Dict",
64
+ "description": "An opaque `Dict`. The type is opaque because the module maintains some\n invariant, namely: there's only one occurrence of a given key in the dictionary.\n\n Note that the `key` parameter is a phantom-type, and only present as a\n means of documentation. Keys can be any type, yet will need to comparable\n to use functions like `insert`.\n\n See for example:\n\n ```aiken\n pub type Value =\n Dict<PolicyId, Dict<AssetName, Int>>\n ```",
65
+ "dataType": "map",
66
+ "keys": {
67
+ "$ref": "#/definitions/ByteArray"
68
+ },
69
+ "values": {
70
+ "$ref": "#/definitions/Int"
71
+ }
72
+ },
73
+ "aiken/transaction/credential/Address": {
74
+ "title": "Address",
75
+ "description": "A Cardano `Address` typically holding one or two credential references.\n\n Note that legacy bootstrap addresses (a.k.a. 'Byron addresses') are\n completely excluded from Plutus contexts. Thus, from an on-chain\n perspective only exists addresses of type 00, 01, ..., 07 as detailed\n in [CIP-0019 :: Shelley Addresses](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0019/#shelley-addresses).",
76
+ "anyOf": [
77
+ {
78
+ "title": "Address",
79
+ "dataType": "constructor",
80
+ "index": 0,
81
+ "fields": [
82
+ {
83
+ "title": "payment_credential",
84
+ "$ref": "#/definitions/aiken~1transaction~1credential~1Credential"
85
+ },
86
+ {
87
+ "title": "stake_credential",
88
+ "$ref": "#/definitions/Option$aiken~1transaction~1credential~1Referenced$aiken~1transaction~1credential~1Credential"
89
+ }
90
+ ]
91
+ }
92
+ ]
93
+ },
94
+ "aiken/transaction/credential/Credential": {
95
+ "title": "Credential",
96
+ "description": "A general structure for representing an on-chain `Credential`.\n\n Credentials are always one of two kinds: a direct public/private key\n pair, or a script (native or Plutus).",
97
+ "anyOf": [
98
+ {
99
+ "title": "VerificationKeyCredential",
100
+ "dataType": "constructor",
101
+ "index": 0,
102
+ "fields": [
103
+ {
104
+ "$ref": "#/definitions/ByteArray"
105
+ }
106
+ ]
107
+ },
108
+ {
109
+ "title": "ScriptCredential",
110
+ "dataType": "constructor",
111
+ "index": 1,
112
+ "fields": [
113
+ {
114
+ "$ref": "#/definitions/ByteArray"
115
+ }
116
+ ]
117
+ }
118
+ ]
119
+ },
120
+ "aiken/transaction/credential/Referenced$aiken/transaction/credential/Credential": {
121
+ "title": "Referenced",
122
+ "description": "Represent a type of object that can be represented either inline (by hash)\n or via a reference (i.e. a pointer to an on-chain location).\n\n This is mainly use for capturing pointers to a stake credential\n registration certificate in the case of so-called pointer addresses.",
123
+ "anyOf": [
124
+ {
125
+ "title": "Inline",
126
+ "dataType": "constructor",
127
+ "index": 0,
128
+ "fields": [
129
+ {
130
+ "$ref": "#/definitions/aiken~1transaction~1credential~1Credential"
131
+ }
132
+ ]
133
+ },
134
+ {
135
+ "title": "Pointer",
136
+ "dataType": "constructor",
137
+ "index": 1,
138
+ "fields": [
139
+ {
140
+ "title": "slot_number",
141
+ "$ref": "#/definitions/Int"
142
+ },
143
+ {
144
+ "title": "transaction_index",
145
+ "$ref": "#/definitions/Int"
146
+ },
147
+ {
148
+ "title": "certificate_index",
149
+ "$ref": "#/definitions/Int"
150
+ }
151
+ ]
152
+ }
153
+ ]
154
+ },
155
+ "aiken/transaction/value/Value": {
156
+ "title": "Value",
157
+ "description": "A multi-asset output `Value`. Contains tokens indexed by [PolicyId](#PolicyId) and [AssetName](#AssetName).\n\n This type maintain some invariants by construction; in particular, a `Value` will never contain a\n zero quantity of a particular token.",
158
+ "dataType": "map",
159
+ "keys": {
160
+ "$ref": "#/definitions/ByteArray"
161
+ },
162
+ "values": {
163
+ "$ref": "#/definitions/aiken~1dict~1Dict$ByteArray_Int"
164
+ }
165
+ },
166
+ "swap/SwapDatum": {
167
+ "title": "SwapDatum",
168
+ "anyOf": [
169
+ {
170
+ "title": "SwapDatum",
171
+ "dataType": "constructor",
172
+ "index": 0,
173
+ "fields": [
174
+ {
175
+ "title": "initiator",
176
+ "$ref": "#/definitions/aiken~1transaction~1credential~1Address"
177
+ },
178
+ {
179
+ "title": "to_provide",
180
+ "$ref": "#/definitions/aiken~1transaction~1value~1Value"
181
+ },
182
+ {
183
+ "title": "to_receive",
184
+ "$ref": "#/definitions/aiken~1transaction~1value~1Value"
185
+ }
186
+ ]
187
+ }
188
+ ]
189
+ },
190
+ "swap/SwapRedeemer": {
191
+ "title": "SwapRedeemer",
192
+ "anyOf": [
193
+ {
194
+ "title": "Cancel",
195
+ "dataType": "constructor",
196
+ "index": 0,
197
+ "fields": []
198
+ },
199
+ {
200
+ "title": "Swap",
201
+ "dataType": "constructor",
202
+ "index": 1,
203
+ "fields": []
204
+ }
205
+ ]
206
+ }
207
+ }
208
+ }
@@ -0,0 +1,55 @@
1
+ # swap
2
+
3
+ Write validators in the `validators` folder, and supporting functions in the `lib` folder using `.ak` as a file extension.
4
+
5
+ For example, as `validators/always_true.ak`
6
+
7
+ ```gleam
8
+ validator {
9
+ fn spend(_datum: Data, _redeemer: Data, _context: Data) -> Bool {
10
+ True
11
+ }
12
+ }
13
+ ```
14
+
15
+ ## Building
16
+
17
+ ```sh
18
+ aiken build
19
+ ```
20
+
21
+ ## Testing
22
+
23
+ You can write tests in any module using the `test` keyword. For example:
24
+
25
+ ```gleam
26
+ test foo() {
27
+ 1 + 1 == 2
28
+ }
29
+ ```
30
+
31
+ To run all tests, simply do:
32
+
33
+ ```sh
34
+ aiken check
35
+ ```
36
+
37
+ To run only tests matching the string `foo`, do:
38
+
39
+ ```sh
40
+ aiken check -m foo
41
+ ```
42
+
43
+ ## Documentation
44
+
45
+ If you're writing a library, you might want to generate an HTML documentation for it.
46
+
47
+ Use:
48
+
49
+ ```sh
50
+ aiken docs
51
+ ```
52
+
53
+ ## Resources
54
+
55
+ Find more on the [Aiken's user manual](https://aiken-lang.org).
@@ -0,0 +1,188 @@
1
+ use aiken/transaction.{
2
+ Input, ScriptContext, Spend, Transaction, find_input, placeholder,
3
+ }
4
+ use aiken/transaction/credential.{Address}
5
+ use aiken/transaction/value.{
6
+ AssetName, PolicyId, from_asset, from_asset_list, from_lovelace,
7
+ }
8
+ use sidan_placeholder/address.{mock_pub_key_address, mock_script_address}
9
+ use sidan_placeholder/builder.{
10
+ complete, new_tx_tester, tx_in, tx_in_inline_datum, tx_out,
11
+ }
12
+ use sidan_placeholder/key_hex.{mock_pub_key_hex}
13
+ use sidan_placeholder/output_reference.{mock_tx_hash, mock_utxo_ref}
14
+ use sidan_utils/address.{address_pub_key} as sidan_address
15
+ use sidan_utils/extra_signatories.{key_signed}
16
+ use sidan_utils/inputs.{inputs_at}
17
+ use sidan_utils/value.{get_all_value_from,
18
+ get_all_value_to, value_geq} as sidan_value
19
+
20
+ pub type MValue =
21
+ Pairs<PolicyId, Pairs<AssetName, Int>>
22
+
23
+ pub type SwapDatum {
24
+ SwapDatum { initiator: Address, to_provide: MValue, to_receive: MValue }
25
+ }
26
+
27
+ pub type SwapRedeemer {
28
+ Cancel
29
+ Swap
30
+ }
31
+
32
+ validator {
33
+ fn swap(datum: SwapDatum, redeemer: SwapRedeemer, ctx: ScriptContext) {
34
+ when ctx.purpose is {
35
+ Spend(utxo) ->
36
+ when redeemer is {
37
+ Swap -> {
38
+ expect Some(own_input) = find_input(ctx.transaction.inputs, utxo)
39
+ let own_address = own_input.output.address
40
+ let inputs_from_script =
41
+ inputs_at(ctx.transaction.inputs, own_address)
42
+ let is_only_one_input_from_script =
43
+ when inputs_from_script is {
44
+ [_] -> True
45
+ _ -> False
46
+ }
47
+
48
+ let is_proceed_paid =
49
+ get_all_value_to(ctx.transaction.outputs, datum.initiator)
50
+ |> value_geq(datum.to_receive |> from_asset_list())
51
+ let is_token_unlocked =
52
+ get_all_value_from(inputs_from_script, own_address)
53
+ |> value_geq(datum.to_provide |> from_asset_list())
54
+ is_only_one_input_from_script && is_token_unlocked && is_proceed_paid
55
+ }
56
+ Cancel -> {
57
+ expect Some(pub_key) = address_pub_key(datum.initiator)
58
+ key_signed(ctx.transaction.extra_signatories, pub_key)
59
+ }
60
+ }
61
+ _ -> False
62
+ }
63
+ }
64
+ }
65
+
66
+ type SwapTestCase {
67
+ is_only_one_input_from_script: Bool,
68
+ is_token_unlocked: Bool,
69
+ is_proceed_paid: Bool,
70
+ }
71
+
72
+ fn get_swap_test_tx(test_case: SwapTestCase) {
73
+ let SwapTestCase {
74
+ is_only_one_input_from_script,
75
+ is_token_unlocked,
76
+ is_proceed_paid,
77
+ } = test_case
78
+
79
+ new_tx_tester()
80
+ |> tx_in(
81
+ True,
82
+ mock_tx_hash(1),
83
+ 1,
84
+ from_lovelace(
85
+ if is_token_unlocked {
86
+ 15_000_000
87
+ } else {
88
+ 10_000_000
89
+ },
90
+ ),
91
+ mock_script_address(1, None),
92
+ )
93
+ |> tx_in_inline_datum(True, swap_datum())
94
+ |> tx_in(
95
+ !is_only_one_input_from_script,
96
+ mock_tx_hash(1),
97
+ 1,
98
+ from_lovelace(10_000_000),
99
+ mock_script_address(1, None),
100
+ )
101
+ |> tx_in_inline_datum(!is_only_one_input_from_script, swap_datum())
102
+ |> tx_out(
103
+ is_proceed_paid,
104
+ mock_pub_key_address(1, None),
105
+ from_asset("test", "test", 1_000),
106
+ )
107
+ |> complete()
108
+ }
109
+
110
+ fn swap_datum() -> SwapDatum {
111
+ SwapDatum {
112
+ initiator: mock_pub_key_address(1, None),
113
+ to_provide: [Pair("", [Pair("", 15_000_000)])],
114
+ to_receive: [Pair("test", [Pair("test", 1_000)])],
115
+ }
116
+ }
117
+
118
+ test success_swapping() {
119
+ let output_reference = mock_utxo_ref(1, 1)
120
+ let test_case =
121
+ SwapTestCase {
122
+ is_only_one_input_from_script: True,
123
+ is_token_unlocked: True,
124
+ is_proceed_paid: True,
125
+ }
126
+
127
+ let tx = get_swap_test_tx(test_case)
128
+ let ctx = ScriptContext { purpose: Spend(output_reference), transaction: tx }
129
+ swap(swap_datum(), Swap, ctx)
130
+ }
131
+
132
+ test fail_swapping_attempting_double_satisfaction() {
133
+ let output_reference = mock_utxo_ref(1, 1)
134
+ let test_case =
135
+ SwapTestCase {
136
+ is_only_one_input_from_script: False,
137
+ is_token_unlocked: True,
138
+ is_proceed_paid: True,
139
+ }
140
+
141
+ let tx = get_swap_test_tx(test_case)
142
+ let ctx = ScriptContext { purpose: Spend(output_reference), transaction: tx }
143
+ !swap(swap_datum(), Swap, ctx)
144
+ }
145
+
146
+ test fail_swapping_without_sufficient_proceed() {
147
+ let output_reference = mock_utxo_ref(1, 1)
148
+ let test_case =
149
+ SwapTestCase {
150
+ is_only_one_input_from_script: True,
151
+ is_token_unlocked: False,
152
+ is_proceed_paid: True,
153
+ }
154
+
155
+ let tx = get_swap_test_tx(test_case)
156
+ let ctx = ScriptContext { purpose: Spend(output_reference), transaction: tx }
157
+ !swap(swap_datum(), Swap, ctx)
158
+ }
159
+
160
+ test fail_swapping_without_proceed_paid() {
161
+ let output_reference = mock_utxo_ref(1, 1)
162
+ let test_case =
163
+ SwapTestCase {
164
+ is_only_one_input_from_script: True,
165
+ is_token_unlocked: True,
166
+ is_proceed_paid: False,
167
+ }
168
+
169
+ let tx = get_swap_test_tx(test_case)
170
+ let ctx = ScriptContext { purpose: Spend(output_reference), transaction: tx }
171
+ !swap(swap_datum(), Swap, ctx)
172
+ }
173
+
174
+ test success_cancel() {
175
+ let output_reference = mock_utxo_ref(1, 1)
176
+ let tx =
177
+ Transaction { ..placeholder(), extra_signatories: [mock_pub_key_hex(1)] }
178
+ let ctx = ScriptContext { purpose: Spend(output_reference), transaction: tx }
179
+ swap(swap_datum(), Cancel, ctx)
180
+ }
181
+
182
+ test fail_cancel_without_key() {
183
+ let output_reference = mock_utxo_ref(1, 1)
184
+ let tx =
185
+ Transaction { ..placeholder(), extra_signatories: [mock_pub_key_hex(2)] }
186
+ let ctx = ScriptContext { purpose: Spend(output_reference), transaction: tx }
187
+ !swap(swap_datum(), Cancel, ctx)
188
+ }
@@ -0,0 +1 @@
1
+ export * from './offchain';
@@ -0,0 +1,139 @@
1
+ import {
2
+ Asset,
3
+ conStr0,
4
+ ConStr0,
5
+ mConStr0,
6
+ mConStr1,
7
+ parsePlutusValueToAssets,
8
+ pubKeyAddress,
9
+ PubKeyAddress,
10
+ UTxO,
11
+ value,
12
+ Value,
13
+ } from "@meshsdk/common";
14
+ import {
15
+ deserializeAddress,
16
+ deserializeDatum,
17
+ serializeAddressObj,
18
+ serializePlutusScript,
19
+ } from "@meshsdk/core";
20
+ import { applyParamsToScript } from "@meshsdk/core-csl";
21
+
22
+ import { MeshTxInitiator, MeshTxInitiatorInput } from "../common";
23
+ import blueprint from "./aiken-workspace/plutus.json";
24
+
25
+ export const MeshSwapBlueprint = blueprint;
26
+
27
+ export type SwapDatum = ConStr0<[PubKeyAddress, Value, Value]>;
28
+
29
+ export class MeshSwapContract extends MeshTxInitiator {
30
+ scriptCbor = applyParamsToScript(blueprint.validators[0]!.compiledCode, []);
31
+ scriptAddress: string;
32
+
33
+ constructor(inputs: MeshTxInitiatorInput) {
34
+ super(inputs);
35
+ this.scriptAddress = serializePlutusScript(
36
+ { code: this.scriptCbor, version: "V2" },
37
+ undefined,
38
+ 0,
39
+ ).address;
40
+ }
41
+
42
+ initiateSwap = async (
43
+ toProvide: Asset[],
44
+ toReceive: Asset[],
45
+ ): Promise<string> => {
46
+ const { utxos, walletAddress, collateral } =
47
+ await this.getWalletInfoForTx();
48
+ const { pubKeyHash, stakeCredentialHash } =
49
+ deserializeAddress(walletAddress);
50
+ const swapDatum: SwapDatum = conStr0([
51
+ pubKeyAddress(pubKeyHash, stakeCredentialHash),
52
+ value(toProvide),
53
+ value(toReceive),
54
+ ]);
55
+
56
+ await this.mesh
57
+ .txOut(this.scriptAddress, toProvide)
58
+ .txOutInlineDatumValue(swapDatum, "JSON")
59
+ .changeAddress(walletAddress)
60
+ .txInCollateral(
61
+ collateral.input.txHash,
62
+ collateral.input.outputIndex,
63
+ collateral.output.amount,
64
+ collateral.output.address,
65
+ )
66
+ .selectUtxosFrom(utxos)
67
+ .complete();
68
+
69
+ return this.mesh.txHex;
70
+ };
71
+
72
+ acceptSwap = async (swapUtxo: UTxO): Promise<string> => {
73
+ const { utxos, walletAddress, collateral } =
74
+ await this.getWalletInfoForTx();
75
+ const inlineDatum = deserializeDatum<SwapDatum>(
76
+ swapUtxo.output.plutusData!,
77
+ );
78
+ const initiatorAddress = serializeAddressObj(inlineDatum.fields[0]);
79
+ const initiatorToReceive = inlineDatum.fields[2];
80
+
81
+ await this.mesh
82
+ .spendingPlutusScriptV2()
83
+ .txIn(
84
+ swapUtxo.input.txHash,
85
+ swapUtxo.input.outputIndex,
86
+ swapUtxo.output.amount,
87
+ swapUtxo.output.address,
88
+ )
89
+ .spendingReferenceTxInInlineDatumPresent()
90
+ .spendingReferenceTxInRedeemerValue(mConStr1([]))
91
+ .txInScript(this.scriptCbor)
92
+ .txOut(initiatorAddress, parsePlutusValueToAssets(initiatorToReceive))
93
+ .changeAddress(walletAddress)
94
+ .txInCollateral(
95
+ collateral.input.txHash,
96
+ collateral.input.outputIndex,
97
+ collateral.output.amount,
98
+ collateral.output.address,
99
+ )
100
+ .selectUtxosFrom(utxos)
101
+ .complete();
102
+ return this.mesh.txHex;
103
+ };
104
+
105
+ cancelSwap = async (swapUtxo: UTxO): Promise<string> => {
106
+ const { utxos, walletAddress, collateral } =
107
+ await this.getWalletInfoForTx();
108
+ const inlineDatum = deserializeDatum<SwapDatum>(
109
+ swapUtxo.output.plutusData!,
110
+ );
111
+ const initiatorAddress = serializeAddressObj(inlineDatum.fields[0]);
112
+ await this.mesh
113
+ .spendingPlutusScriptV2()
114
+ .txIn(
115
+ swapUtxo.input.txHash,
116
+ swapUtxo.input.outputIndex,
117
+ swapUtxo.output.amount,
118
+ swapUtxo.output.address,
119
+ )
120
+ .spendingReferenceTxInInlineDatumPresent()
121
+ .spendingReferenceTxInRedeemerValue(mConStr0([]))
122
+ .txInScript(this.scriptCbor)
123
+ .changeAddress(walletAddress)
124
+ .txInCollateral(
125
+ collateral.input.txHash,
126
+ collateral.input.outputIndex,
127
+ collateral.output.amount,
128
+ collateral.output.address,
129
+ )
130
+ .requiredSignerHash(deserializeAddress(initiatorAddress).pubKeyHash)
131
+ .selectUtxosFrom(utxos)
132
+ .complete();
133
+ return this.mesh.txHex;
134
+ };
135
+
136
+ getUtxoByTxHash = async (txHash: string): Promise<UTxO | undefined> => {
137
+ return await this._getUtxoByTxHash(this.scriptCbor, txHash);
138
+ };
139
+ }
@@ -0,0 +1,35 @@
1
+ # Swap
2
+
3
+ Swap contract facilitates the exchange of assets between two parties. This contract is designed to be used in a peer-to-peer exchange scenario where two parties agree to exchange assets. The contract ensures that the assets are locked up until it is accepted by the other party. At any point before it is accepted, one can cancel the swap to retrieve the assets.
4
+
5
+ [Demo](https://meshjs.dev/smart-contracts/swap)
6
+
7
+ There are 2 actions (or endpoints) available to interact with this smart contract:
8
+
9
+ - initiate swap
10
+ - accept asset
11
+ - cancel swap
12
+
13
+ To initialize the swap, we need to initialize a provider, MeshTxBuilder and MeshSwapContract.
14
+
15
+ ```typescript
16
+ import { BlockfrostProvider, MeshTxBuilder } from '@meshsdk/core';
17
+ import { MeshSwapContract } from '@meshsdk/contracts';
18
+ import { useWallet } from '@meshsdk/react';
19
+
20
+ const { connected, wallet } = useWallet();
21
+
22
+ const blockchainProvider = new BlockfrostProvider(APIKEY);
23
+
24
+ const meshTxBuilder = new MeshTxBuilder({
25
+ fetcher: blockchainProvider,
26
+ submitter: blockchainProvider,
27
+ });
28
+
29
+ const contract = new MeshSwapContract({
30
+ mesh: meshTxBuilder,
31
+ fetcher: blockchainProvider,
32
+ wallet: wallet,
33
+ networkId: 0,
34
+ });
35
+ ```
@@ -0,0 +1,24 @@
1
+ # Vesting - Specification
2
+
3
+ ## Scripts - VestingValidator
4
+
5
+ The validator of locking vesting value.
6
+
7
+ ### Parameter - no parameter
8
+
9
+ ### Datum
10
+
11
+ - `lock_until`: POSIX time in second at locking end, e.g. 1672843961000
12
+ - `owner`: Owner's pub key hash
13
+ - `beneficiary`: Beneficiary's pub key hash
14
+
15
+ ### User Action
16
+
17
+ 1. Unlock by owner
18
+
19
+ - Signed by `owner`
20
+
21
+ 2. Unlock by beneficiary
22
+
23
+ - Signed by `beneficiary`
24
+ - Only valid after `lock_until`
@@ -0,0 +1,26 @@
1
+ # This file was generated by Aiken
2
+ # You typically do not need to edit this file
3
+
4
+ [[requirements]]
5
+ name = "aiken-lang/stdlib"
6
+ version = "1.9.0"
7
+ source = "github"
8
+
9
+ [[requirements]]
10
+ name = "sidan-lab/aiken-utils"
11
+ version = "0.1.6-beta"
12
+ source = "github"
13
+
14
+ [[packages]]
15
+ name = "aiken-lang/stdlib"
16
+ version = "1.9.0"
17
+ requirements = []
18
+ source = "github"
19
+
20
+ [[packages]]
21
+ name = "sidan-lab/aiken-utils"
22
+ version = "0.1.6-beta"
23
+ requirements = []
24
+ source = "github"
25
+
26
+ [etags]