-
Notifications
You must be signed in to change notification settings - Fork 0
/
helpers.cpp
358 lines (268 loc) · 11.2 KB
/
helpers.cpp
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
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#ifndef HEADERFILE_H
#define HEADERFILE_H
void ascensionwx::updateBuilderBalance( name builder, float rewards_multiplier) {
builders_table_t _builders(get_self(), get_first_receiver().value);
auto builders_itr = _builders.find( builder.value );
float usd_amt = 0.25; // Update $0.25 per sensor
if ( rewards_multiplier != 0 ) {
float token_amount = usd_amt * builders_itr->multiplier;
_builders.modify( builders_itr, get_self(), [&](auto& builder) {
builder.balance = builders_itr->balance + token_amount;
builder.number_devices = builders_itr->number_devices + 1;
});
}
}
void ascensionwx::updateRoyaltyBalance( name person, string type ) {
if ( type == "builder" )
{
builders_table_t _builders(get_self(), get_first_receiver().value);
auto builders_itr = _builders.find( person.value );
float usd_amt = 0.25; // Update $0.25 per sensor
float token_amount = usd_amt;
_builders.modify( builders_itr, get_self(), [&](auto& builder) {
builder.balance = builders_itr->balance + token_amount;
builder.number_devices = builders_itr->number_devices + 1;
});
}
else if ( type == "referral" )
{
sponsors_table_t _sponsors(get_self(), get_first_receiver().value);
auto sponsors_itr = _sponsors.find( person.value );
float usd_amt = 0.10; // Update $0.25 per sensor
float token_amount = usd_amt;
_sponsors.modify( sponsors_itr, get_self(), [&](auto& sponsor) {
sponsor.balance = sponsors_itr->balance + token_amount;
sponsor.number_devices = sponsors_itr->number_devices + 1;
});
}
}
void ascensionwx::payoutMiner( name miner, string memo, float balance ) {
minersv2_table_t _miners(get_self(), get_first_receiver().value);
auto miners_itr = _miners.find( miner.value );
string to;
bool evm_enabled = miners_itr->evm_send_enabled;
if ( evm_enabled )
to = miners_itr->evm_address_str;
else
to = miner.to_string();
payout( to, balance, memo , evm_enabled );
// Set Miner's new balance to 0
// Querying get_deltas with RAM payer being self will return prior daily payouts
_miners.modify( miners_itr, get_self(), [&](auto& miner) {
miner.previous_day_pay_usd = balance;
miner.balance = 0;
});
}
void ascensionwx::payoutBuilder( name builder ) {
builders_table_t _builders(get_self(), get_first_receiver().value);
auto builders_itr = _builders.find( builder.value );
// Put number of devices in payout string
uint16_t num_devices = builders_itr->number_devices;
string memo = "Builder payout: " + to_string(num_devices) + " devices reported data today.";
string to;
bool evm_enabled = builders_itr->evm_send_enabled;
if ( evm_enabled )
to = builders_itr->evm_address;
else
to = builder.to_string();
float balance = builders_itr->balance;
payout( to, balance, memo , evm_enabled );
// Set Builder's new balance to 0
_builders.modify( builders_itr, get_self(), [&](auto& builder) {
builder.balance = 0;
builder.number_devices = 0;
});
}
void ascensionwx::payout( string to, float balance, string memo , bool evm_enabled )
{
if (evm_enabled)
check( to.substr(0,2) == "0x" , "AscensionWx payout function not called properly" );
tokensv2_table_t _tokens(get_self(), get_first_receiver().value);
auto tokens_itr = _tokens.find( "eosio.token"_n.value );
float usd_price = tokens_itr->current_usd_price;
float token_amount = balance / usd_price;
// Check for null balance
if ( token_amount == 0 )
return;
uint32_t amt_number = (uint32_t)(pow( 10, tokens_itr->precision ) *
token_amount);
eosio::asset reward = eosio::asset(
amt_number,
symbol(symbol_code( tokens_itr->symbol_letters ), tokens_itr->precision));
if( evm_enabled )
{
payoutEVM( to, amt_number );
} else {
// Do token transfer using an inline function
// This works even with "iot" or another account's key being passed, because even though we're not passing
// the traditional "active" key, the "active" condition is still met with @eosio.code
action(
permission_level{ get_self(), "active"_n },
tokens_itr->token_contract , "transfer"_n,
std::make_tuple( get_self(), name(to), reward, memo)
).send();
}
}
void ascensionwx::payoutEVM( string receiver, float amt_number )
{
check( receiver.substr(0,2) == "0x" , "AscensionWx payout function not called properly" );
int chain_id = 40; // Telos EVM Mainnet
// Eventually we want to store this in the parameters table
string own_address_str = "0xcE1247ef3f22a44F6D01777A9A0E0634E28Da254";
checksum160 own_address = evm_string_to_checksum160( own_address_str );
/*
string wtlos = "0xD102cE6A4dB07D247fcc28F366A623Df0938CA9E";
std::array<uint8_t, 20u> wtlos_array = eosio_evm::toBin( wtlos.substr(2) );
std::vector<uint8_t> wtlos_vector;
wtlos_vector.insert( wtlos_vector.end(), wtlos_array.begin(), wtlos_array.end() );
*/
// Receiver's account
std::array<uint8_t, 20u> receiver_array = eosio_evm::toBin( receiver.substr(2) );
std::vector<uint8_t> receiver_vector;
receiver_vector.insert( receiver_vector.end(), receiver_array.begin(), receiver_array.end() );
// Amount to transfer
// EVM number of digits is 14 . We pad with up to 16 zeros in case it is necessary
vector<uint8_t> amt_vector = eosio_evm::pad(intx::to_byte_string(amt_number * pow (10, 14)), 16, true);
// Set gas limit and get gas prices
uint256_t gas_limit = 500000;
evm_config_table_t _evmconfig( name("eosio.evm"), name("eosio.evm").value );
checksum256 entry = _evmconfig.get().gas_price;
uint256_t gas_price = eosio_evm::checksum256ToValue( entry );
// Get nonce of own account
checksum160 evm_address160 = evm_string_to_checksum160( own_address_str );
evm_table_t _evmaccounts( name("eosio.evm"), name("eosio.evm").value );
auto acct_index = _evmaccounts.get_index<"byaddress"_n>();
checksum256 address = eosio_evm::pad160(evm_address160);
auto evm_itr = acct_index.find( address );
uint64_t nonce = evm_itr->nonce;
// Encodes all the data for our EVM transaction
string tx = rlp::encode(nonce, gas_price, gas_limit,
receiver_vector,
amt_vector,
0, 0, 0, 0);
action(
permission_level {get_self(), "active"_n},
"eosio.evm"_n,
"raw"_n,
std::make_tuple(get_self(), tx, false, std::optional<eosio::checksum160>(own_address))
).send();
}
void ascensionwx::handleIfNewPeriod( uint64_t now )
{
parameters_table_t _parameters(get_self(), get_first_receiver().value);
auto parameters_itr = _parameters.begin();
// Final check is to see if we need to update the period
if ( now > parameters_itr->period_end_time ) {
action(
permission_level{ get_self(), "active"_n },
get_self(), "newperiod"_n,
std::make_tuple( parameters_itr->period_end_time ) // set start time to last period's end time
).send();
}
}
float ascensionwx::calcDistance( float lat1, float lon1, float lat2, float lon2 )
{
// This function uses the given lat/lon of the devices to deterimine
// the distance between them.
// The calculation is made using the Haversine method and utilizes Math.h
float R = 6372800; // Earth radius in meters
float phi1 = degToRadians(lat1);
float phi2 = degToRadians(lat2);
float dphi = degToRadians( lat2 - lat1 );
float dlambda = degToRadians( lon2 - lon1 );
float a = pow(sin(dphi/2), 2) + pow( cos(phi1)*cos(phi2)*sin(dlambda/2.0) , 2);
float distance_meters = 2*R*atan2( sqrt(a) , sqrt(1-a) );
// return distance in km
return distance_meters/1000.0;
}
float ascensionwx::degToRadians( float degrees )
{
// M_PI comes from math.h
return (degrees * M_PI) / 180.0;
}
float ascensionwx::calcDewPoint( float temperature_c, float humidity ) {
const float c1 = 243.04;
const float c2 = 17.625;
float h = humidity / 100;
if (h <= 0.01)
h = 0.01;
else if (h > 1.0)
h = 1.0;
const float lnh = log(h); // natural logarithm
const float tpc1 = temperature_c + c1;
const float txc2 = temperature_c * c2;
float txc2_tpc1 = txc2 / tpc1;
float tdew = c1 * (lnh + txc2_tpc1) / (c2 - lnh - txc2_tpc1);
return tdew;
}
bool ascensionwx::check_bit( uint8_t flags, uint8_t target_flag ) {
for( int i=128; i>0; i=i/2 ) {
bool flag_enabled = ( flags - i >= 0 );
if( i==target_flag )
return flag_enabled;
if( flag_enabled )
flags -= i;
}
return false; // If target flag never reached return false
}
bool ascensionwx::if_physical_damage( uint8_t flags ) {
return check_bit(flags,128); // Flag representing phyiscal damage
}
bool ascensionwx::if_indoor_flagged( uint8_t flags, float temperature_c ) {
// If temperature is between 66 and 78 farenheight, check sensor variance flag
if ( temperature_c > 18.9 && temperature_c < 25.5 )
return check_bit(flags,16); // Flag for very low temperature variance
else
return false;
}
string ascensionwx::evmLookup( name account )
{
// Look up the EVM address from the evm contract
evm_table_t _evmaccounts( name("eosio.evm"), name("eosio.evm").value );
auto acct_index = _evmaccounts.get_index<"byaccount"_n>();
auto evm_itr = acct_index.find( account.value ); // Use miner's name to query
checksum160 evmaddress = evm_itr->address;
std::array<uint8_t, 32u> bytes = eosio_evm::fromChecksum160( evmaddress );
// Convert to hex and chop off padded bytes
return "0x" + eosio_evm::bin2hex(bytes).substr(24);
}
void ascensionwx::handleClimateContracts(name devname, float latitude, float longitude)
{
}
void ascensionwx::handleIfSensorAlreadyHere( name devname,
float latitude_deg,
float longitude_deg )
{
// Set reward for this sensor to 0 if there is one in same exact location
weather_table_t _weather(get_self(), get_first_receiver().value );
auto lon_index = _weather.get_index<"longitude"_n>();
auto lon_itr = lon_index.lower_bound( longitude_deg );
rewardsv2_table_t _rewards( get_self(), get_first_receiver().value );
bool another_sensor_here = false;
uint64_t now = current_time_point().sec_since_epoch();
bool unique;
for ( auto itr = lon_itr ; itr->longitude_deg == longitude_deg && itr != lon_index.end() ; itr++ )
{
if ( itr->latitude_deg == latitude_deg )
{
// Change all other sensors in exact same location to have multiplier = 0
if ( itr->devname != devname ) {
unique = false;
another_sensor_here = true;
} else
unique = true;
auto rewards_itr = _rewards.find( itr->devname.value );
_rewards.modify(rewards_itr, get_self(), [&](auto& reward) {
reward.unique_location = unique;
});
} // End same exact latitude check
} // End same exact longitude check
// Finally, if no sensors in same location, but multiplier
// was set to 0 in the past, then set multiplier to 1
auto this_rewards_itr = _rewards.find( devname.value );
if ( another_sensor_here == false && this_rewards_itr->unique_location == false )
_rewards.modify(this_rewards_itr, get_self(), [&](auto& reward) {
reward.unique_location = true;
});
}
#endif