polarloop 1.0.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 337da4304503c173f43227da0bbe06c0a0e8b6f2638ad906cd909fd78db86d3b
4
+ data.tar.gz: 6c28562afb905de9c8fe5fe47b75856ef4c4fb4b0b677e8981e8739f9d4f3763
5
+ SHA512:
6
+ metadata.gz: c38b666ad7a4258379b5cb770e887b904b46718516934c6c98f18d36bce410a7422654f1c4faf0558355e1eac8198225f6aed7cede03859346a227a835f6ff44
7
+ data.tar.gz: d104fef27a6e96af8c80b1c9959f82299abd0e5b81453bc4feec263d484c3889de14ed94a8a57eca5ce3c3e89c39be69fb7257670bbbc94a42ddaf05f7f242f6
data/CHANGELOG.md ADDED
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ ## 2026-06-30 00:00 — Release 1.0.0 on RubyGems.org
4
+
5
+ - Bump version to 1.0.0 (first public release)
6
+ - Add MIT LICENSE file (copyright Pontifi)
7
+ - gemspec: set author to Pontifi, homepage to RubyGems gem page, MIT metadata (allowed_push_host, homepage_uri); include CHANGELOG.md in packaged files
8
+ - README: replace internal GitLab install instructions with `gem install polarloop`
9
+
10
+ ## 2026-03-15 07:00 — Initial gem implementation
11
+
12
+ - Project skeleton: gemspec, Gemfile, Rakefile, .rspec, .gitignore
13
+ - Type structs: Mandate, BatchResult, ChargeReadyResult, TxResult, Event types
14
+ - ABI loading from Hardhat artifact with event topic hashes and error decoding
15
+ - Configuration with multi-chain registration (ChainConfig)
16
+ - BIP-44 wallet derivation from mnemonic (single key per config)
17
+ - Gas strategy: auto-detect EIP-1559 vs Legacy per chain via eth_feeHistory
18
+ - ContractCaller: low-level eth.rb wrapper with eth_call dry-run + eth_estimateGas
19
+ - EventParser: eth_getLogs with MandateCreated/Charged/Revoked decoding
20
+ - Client: full public API — charge, batch_charge, revoke, sign_create_mandate, events, views
21
+ - Manager: multi-chain client registry with cached Client instances
22
+ - Net::HTTP patch for eth.rb (HTTPX hangs on some RPC endpoints)
23
+ - Contract revert decoding: standard Error(string), Panic(uint256), and custom ABI errors
24
+ - Unit tests: 21 specs covering wallet, client, and event parser (WebMock)
25
+ - Verified on BSC Testnet: charge, view calls, event parsing all working
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Pontifi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,223 @@
1
+ # PolarLoop-rb
2
+
3
+ Ruby gem для взаимодействия со смарт-контрактом PolarLoop на EVM-чейнах. Управление мандатами, списание, парсинг событий и генерация подписи оператора для бэкенда AWB.
4
+
5
+ ## Оглавление
6
+
7
+ - [Установка](#установка)
8
+ - [Конфигурация](#конфигурация)
9
+ - [Использование](#использование)
10
+ - [View-методы (без газа)](#view-методы-без-газа)
11
+ - [Write-методы (отправка транзакций)](#write-методы-отправка-транзакций)
12
+ - [Подпись оператора (off-chain, без газа)](#подпись-оператора-off-chain-без-газа)
13
+ - [События](#события)
14
+ - [Адрес кошелька](#адрес-кошелька)
15
+ - [Обработка ошибок](#обработка-ошибок)
16
+ - [Мульти-чейн](#мульти-чейн)
17
+ - [Разработка](#разработка)
18
+ - [Лицензия](#лицензия)
19
+
20
+ ## Установка
21
+
22
+ ```bash
23
+ gem install polarloop
24
+ ```
25
+
26
+ Или добавить в Gemfile:
27
+
28
+ ```ruby
29
+ gem "polarloop"
30
+ ```
31
+
32
+ ## Конфигурация
33
+
34
+ ```ruby
35
+ PolarLoop.configure do |c|
36
+ c.mnemonic = "your twelve word mnemonic phrase here ..."
37
+ c.index = 0 # BIP-44 индекс деривации (m/44'/60'/0'/0/N)
38
+
39
+ c.register(:bsc,
40
+ rpc_url: "https://bsc-dataseed.binance.org",
41
+ contract_address: "0x...",
42
+ chain_id: 56,
43
+ gas_multiplier: 1.2 # опционально, по умолчанию 1.2
44
+ )
45
+
46
+ c.register(:polygon,
47
+ rpc_url: "https://polygon-rpc.com",
48
+ contract_address: "0x...",
49
+ chain_id: 137
50
+ )
51
+ end
52
+ ```
53
+
54
+ ## Использование
55
+
56
+ ```ruby
57
+ client = PolarLoop.client(:bsc)
58
+ ```
59
+
60
+ ### View-методы (без газа)
61
+
62
+ ```ruby
63
+ # Получить мандат по ID
64
+ mandate = client.get_mandate("0xabc...")
65
+ mandate.payer # => "0x..."
66
+ mandate.amount # => 1000000
67
+ mandate.interval # => 86400
68
+ mandate.active # => true
69
+ mandate.reference_id # => "0x..."
70
+
71
+ # Получить мандат по вашему reference ID
72
+ mandate_id, mandate = client.get_mandate_by_reference_id("0xref...")
73
+
74
+ # Проверить готовность к списанию
75
+ result = client.charge_ready?("0xabc...")
76
+ result.ready # => true
77
+ result.reason # => ""
78
+
79
+ # Пакетная проверка
80
+ results = client.batch_charge_ready?(["0xabc...", "0xdef..."])
81
+
82
+ # Все мандаты плательщика
83
+ ids = client.get_payer_mandates("0xpayer...")
84
+
85
+ # Состояние контракта
86
+ client.min_interval # => 86400
87
+ client.paused? # => false
88
+ ```
89
+
90
+ ### Write-методы (отправка транзакций)
91
+
92
+ ```ruby
93
+ # Списание по мандату
94
+ result = client.charge("0xabc...")
95
+ result.tx_hash # => "0x..."
96
+ result.block_number # => 12345678
97
+ result.gas_used # => 71356
98
+ result.status # => true
99
+
100
+ # Пакетное списание
101
+ result = client.batch_charge(["0xabc...", "0xdef..."])
102
+ result.batch_results[0].mandate_id # => "0xabc..."
103
+ result.batch_results[0].success # => true
104
+ result.batch_results[1].mandate_id # => "0xdef..."
105
+ result.batch_results[1].success # => false
106
+ result.batch_results[1].reason # => "Interval not elapsed"
107
+
108
+ # Отзыв мандата
109
+ result = client.revoke_mandate("0xabc...")
110
+ result = client.batch_revoke_mandate(["0xabc...", "0xdef..."])
111
+
112
+ # Админские методы
113
+ client.pause
114
+ client.unpause
115
+ client.grant_operator_role("0xaddress...")
116
+ client.revoke_operator_role("0xaddress...")
117
+ client.rescue_eth
118
+ client.rescue_erc20("0xtoken...", amount)
119
+ ```
120
+
121
+ ### Подпись оператора (off-chain, без газа)
122
+
123
+ Генерация ECDSA-подписи для `createMandate` на фронтенде:
124
+
125
+ ```ruby
126
+ signature = client.sign_create_mandate(
127
+ payer: "0xpayer...",
128
+ merchant: "0xmerchant...",
129
+ token: "0xtoken...",
130
+ amount: 1_000_000,
131
+ interval: 86_400,
132
+ max_total_amount: 10_000_000,
133
+ reference_id: "0xref..."
134
+ )
135
+ # => "abcdef1234..." (hex-подпись для dApp)
136
+ ```
137
+
138
+ ### События
139
+
140
+ ```ruby
141
+ # MandateCreated — создание мандата
142
+ events = client.mandate_created_events(from_block: 1000, to_block: "latest")
143
+ events.each do |e|
144
+ e.mandate_id # => "0x..."
145
+ e.payer # => "0x..."
146
+ e.merchant # => "0x..."
147
+ e.token # => "0x..."
148
+ e.amount # => 1000000
149
+ e.interval # => 86400
150
+ e.max_total_amount # => 10000000
151
+ e.reference_id # => "0x..."
152
+ e.block_number # => 12345
153
+ e.tx_hash # => "0x..."
154
+ end
155
+
156
+ # MandateCharged — списание по мандату
157
+ events = client.mandate_charged_events(from_block: 1000)
158
+ events.each do |e|
159
+ e.mandate_id # => "0x..."
160
+ e.payer # => "0x..."
161
+ e.merchant # => "0x..."
162
+ e.amount # => 1000000
163
+ e.timestamp # => 1773521124
164
+ e.block_number # => 12345
165
+ e.tx_hash # => "0x..."
166
+ end
167
+
168
+ # MandateRevoked — отзыв мандата
169
+ events = client.mandate_revoked_events(from_block: 1000)
170
+ events.each do |e|
171
+ e.mandate_id # => "0x..."
172
+ e.payer # => "0x..."
173
+ e.block_number # => 12345
174
+ e.tx_hash # => "0x..."
175
+ end
176
+
177
+ # События конкретной транзакции
178
+ events = client.events_for_tx("0xtxhash...")
179
+ ```
180
+
181
+ ### Адрес кошелька
182
+
183
+ ```ruby
184
+ PolarLoop.address # => "0x..." (из мнемоники + индекса)
185
+ ```
186
+
187
+ ## Обработка ошибок
188
+
189
+ ```ruby
190
+ begin
191
+ client.charge("0xabc...")
192
+ rescue PolarLoop::ContractRevertError => e
193
+ # Контракт отклонил вызов — декодированная ошибка из ABI
194
+ # например: "AccessControlUnauthorizedAccount(0x..., 0x...)"
195
+ # например: "Interval not elapsed"
196
+ puts e.message
197
+ rescue PolarLoop::RpcError => e
198
+ # Ошибка соединения или протокола RPC
199
+ puts e.message
200
+ end
201
+ ```
202
+
203
+ ## Мульти-чейн
204
+
205
+ Регистрируйте несколько чейнов и получайте отдельные клиенты:
206
+
207
+ ```ruby
208
+ bsc_client = PolarLoop.client(:bsc)
209
+ polygon_client = PolarLoop.client(:polygon)
210
+ ```
211
+
212
+ Один и тот же адрес кошелька на всех EVM-чейнах (BIP-44 деривация).
213
+
214
+ ## Разработка
215
+
216
+ ```bash
217
+ bundle install
218
+ bundle exec rspec
219
+ ```
220
+
221
+ ## Лицензия
222
+
223
+ MIT