forked from ton-blockchain/wallet-contract
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsubscription-plugin.fc
126 lines (112 loc) · 4.17 KB
/
subscription-plugin.fc
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
;; Simple subscription plugin for wallet-v4
(int) equal_slices (slice s1, slice s2) asm "SDEQ";
;; storage$_ payer_address:MsgAddressInt
;; payee_address:MsgAddressInt
;; amount:uint120
;; subs_period:uint32 last_payment:uint32
;; request_timeout:uint32 last_request:uint32 = Storage;
(slice, slice, int, int, int, int, int) load_storage () {
var ds = get_data().begin_parse();
return
( ds~load_msg_addr(),
ds~load_msg_addr(),
ds~load_uint(120),
ds~load_uint(32),
ds~load_uint(32),
ds~load_uint(32),
ds~load_uint(32)
);
}
() save_storage (slice payer_address,
slice payee_address,
int amount, int period, int last_payment,
int timeout, int last_request) impure {
set_data(begin_cell()
.store_slice(payer_address)
.store_slice(payee_address)
.store_uint(amount, 120)
.store_uint(period, 32)
.store_uint(last_payment,32)
.store_uint(timeout, 32)
.store_uint(last_request,32)
.end_cell());
}
() forward_funds (slice destination, int self_destruct) impure {
if (~ self_destruct) {
raw_reserve(1000000000, 2);
}
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(destination)
.store_grams(0)
.store_dict(pair_second(get_balance()))
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1);
int mode = 128;
if (self_destruct) {
mode += 32;
}
send_raw_message(msg.end_cell(), mode);
}
() request_subscription_payment(slice payer_address, int requested_amount) impure {
var msg = begin_cell()
.store_uint(0x18, 6)
.store_slice(payer_address)
.store_grams(100000000)
.store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 + 1)
.store_uint(0x706c7567, 32) ;; request op
.store_grams(requested_amount)
.store_uint(0,1); ;; empty extra
send_raw_message(msg.end_cell(), 1);
}
() recv_internal(int msg_value, cell in_msg_cell, slice in_msg) impure {
var cs = in_msg_cell.begin_parse();
var flags = cs~load_uint(4);
slice s_addr = cs~load_msg_addr();
(slice payer_address, slice payee_address,
int amount, int period, int last_payment,
int timeout, int last_request) =
load_storage();
if(last_request == 0) {
request_subscription_payment(payer_address, amount);
save_storage(payer_address, payee_address, amount, period, last_payment, timeout, now());
}
if ( ~ equal_slices(s_addr, payer_address)) {
;; proxy all funds to payer_address
;; TODO check whether here should be payee_address
return forward_funds(payer_address, 0);
}
;; funds from payer
int op = in_msg~load_uint(32);
if(op == 0xde511201) { ;; request to destroy
return forward_funds(payee_address, -1);
}
if(op == 0x706c7567) { ;; plugin access
if(last_payment + period > now()) {
;; new payment came too soon
;; result of lags in network when new request for payment was emitted
;; before prev one was processed and as result to payment were generated
return forward_funds(payer_address, 0);
}
;;TODO should we check and compare arrived funds with amount???
forward_funds(payee_address, 0);
return save_storage(payer_address, payee_address, amount, period, now(), timeout, last_request);
}
}
() recv_external(slice in_msg) impure {
(slice payer_address, slice payee_address,
int amount, int period, int last_payment,
int timeout, int last_request) =
load_storage();
throw_unless(130, (last_request + timeout < now()) & (last_payment + period < now()));
return request_subscription_payment(payer_address, amount);
}
;; Get methods
([int, int],[int, int], int, int, int, int, int) get_subscription_data() method_id {
(slice payer_address, slice payee_address,
int amount, int period, int last_payment,
int timeout, int last_request) =
load_storage();
(int mwc, int mad) = parse_std_addr(payer_address);
(int dwc, int dad) = parse_std_addr(payee_address);
return (pair(mwc, mad), pair(dwc, dad), amount, period, last_payment, timeout, last_request);
}