Update nostr gem, switch to Ruby for bech32 encoding
This commit is contained in:
parent
1a5a2177b4
commit
b4f0c60ea0
2
Gemfile
2
Gemfile
@ -62,7 +62,7 @@ gem "sentry-rails"
|
|||||||
gem 'discourse_api'
|
gem 'discourse_api'
|
||||||
gem "lnurl"
|
gem "lnurl"
|
||||||
gem 'manifique', git: 'https://gitea.kosmos.org/5apps/manifique.git', branch: 'master'
|
gem 'manifique', git: 'https://gitea.kosmos.org/5apps/manifique.git', branch: 'master'
|
||||||
gem 'nostr', git: 'https://gitea.kosmos.org/kosmos/nostr-gem.git', branch: 'feature/ruby_2.7_compat'
|
gem 'nostr', git: 'https://gitea.kosmos.org/kosmos/nostr-gem.git', ref: 'd59f31a'
|
||||||
|
|
||||||
group :development, :test do
|
group :development, :test do
|
||||||
# Use sqlite3 as the database for Active Record
|
# Use sqlite3 as the database for Active Record
|
||||||
|
18
Gemfile.lock
18
Gemfile.lock
@ -10,12 +10,12 @@ GIT
|
|||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: https://gitea.kosmos.org/kosmos/nostr-gem.git
|
remote: https://gitea.kosmos.org/kosmos/nostr-gem.git
|
||||||
revision: 596529d9eb50d13b3f385245636698fccf37b442
|
revision: d59f31a3c63c7642fe2d3eb50b785da54fdabfab
|
||||||
branch: feature/ruby_2.7_compat
|
ref: d59f31a
|
||||||
specs:
|
specs:
|
||||||
nostr (0.4.0)
|
nostr (0.5.0)
|
||||||
bech32 (~> 1.3)
|
bech32 (~> 1.4)
|
||||||
bip-schnorr (~> 0.4)
|
bip-schnorr (~> 0.6)
|
||||||
ecdsa (~> 1.2)
|
ecdsa (~> 1.2)
|
||||||
event_emitter (~> 0.2)
|
event_emitter (~> 0.2)
|
||||||
faye-websocket (~> 0.11)
|
faye-websocket (~> 0.11)
|
||||||
@ -115,7 +115,7 @@ GEM
|
|||||||
thor (>= 1.1.0)
|
thor (>= 1.1.0)
|
||||||
benchmark (0.2.1)
|
benchmark (0.2.1)
|
||||||
bindex (0.8.1)
|
bindex (0.8.1)
|
||||||
bip-schnorr (0.6.0)
|
bip-schnorr (0.7.0)
|
||||||
ecdsa_ext (~> 0.5.0)
|
ecdsa_ext (~> 0.5.0)
|
||||||
brow (0.4.1)
|
brow (0.4.1)
|
||||||
builder (3.2.4)
|
builder (3.2.4)
|
||||||
@ -259,6 +259,7 @@ GEM
|
|||||||
method_source (1.0.0)
|
method_source (1.0.0)
|
||||||
mini_magick (4.12.0)
|
mini_magick (4.12.0)
|
||||||
mini_mime (1.1.5)
|
mini_mime (1.1.5)
|
||||||
|
mini_portile2 (2.8.5)
|
||||||
minitest (5.20.0)
|
minitest (5.20.0)
|
||||||
multipart-post (2.3.0)
|
multipart-post (2.3.0)
|
||||||
net-imap (0.3.7)
|
net-imap (0.3.7)
|
||||||
@ -272,6 +273,9 @@ GEM
|
|||||||
net-smtp (0.4.0)
|
net-smtp (0.4.0)
|
||||||
net-protocol
|
net-protocol
|
||||||
nio4r (2.5.9)
|
nio4r (2.5.9)
|
||||||
|
nokogiri (1.15.4)
|
||||||
|
mini_portile2 (~> 2.8.2)
|
||||||
|
racc (~> 1.4)
|
||||||
nokogiri (1.15.4-arm64-darwin)
|
nokogiri (1.15.4-arm64-darwin)
|
||||||
racc (~> 1.4)
|
racc (~> 1.4)
|
||||||
nokogiri (1.15.4-x86_64-linux)
|
nokogiri (1.15.4-x86_64-linux)
|
||||||
@ -422,6 +426,8 @@ GEM
|
|||||||
actionpack (>= 5.2)
|
actionpack (>= 5.2)
|
||||||
activesupport (>= 5.2)
|
activesupport (>= 5.2)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
|
sqlite3 (1.6.7)
|
||||||
|
mini_portile2 (~> 2.8.0)
|
||||||
sqlite3 (1.6.7-arm64-darwin)
|
sqlite3 (1.6.7-arm64-darwin)
|
||||||
sqlite3 (1.6.7-x86_64-linux)
|
sqlite3 (1.6.7-x86_64-linux)
|
||||||
stimulus-rails (1.3.0)
|
stimulus-rails (1.3.0)
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { Controller } from "@hotwired/stimulus"
|
import { Controller } from "@hotwired/stimulus"
|
||||||
import { bech32 } from "bech32"
|
|
||||||
|
|
||||||
function hexToBytes (hex) {
|
function hexToBytes (hex) {
|
||||||
let bytes = []
|
let bytes = []
|
||||||
@ -15,10 +14,6 @@ export default class extends Controller {
|
|||||||
static values = { userAddress: String, pubkeyHex: String, sharedSecret: String }
|
static values = { userAddress: String, pubkeyHex: String, sharedSecret: String }
|
||||||
|
|
||||||
connect () {
|
connect () {
|
||||||
if (this.hasPubkeyHexValue && this.pubkeyHexValue.length > 0) {
|
|
||||||
this.pubkeyBech32InputTarget.value = this.pubkeyBech32
|
|
||||||
}
|
|
||||||
|
|
||||||
if (window.nostr) {
|
if (window.nostr) {
|
||||||
if (this.hasSetPubkeyTarget) {
|
if (this.hasSetPubkeyTarget) {
|
||||||
this.setPubkeyTarget.disabled = false
|
this.setPubkeyTarget.disabled = false
|
||||||
@ -53,11 +48,6 @@ export default class extends Controller {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get pubkeyBech32 () {
|
|
||||||
const words = bech32.toWords(hexToBytes(this.pubkeyHexValue))
|
|
||||||
return bech32.encode('npub', words)
|
|
||||||
}
|
|
||||||
|
|
||||||
get csrfToken () {
|
get csrfToken () {
|
||||||
const element = document.head.querySelector('meta[name="csrf-token"]')
|
const element = document.head.querySelector('meta[name="csrf-token"]')
|
||||||
return element.getAttribute("content")
|
return element.getAttribute("content")
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
require 'nostr'
|
||||||
|
|
||||||
class User < ApplicationRecord
|
class User < ApplicationRecord
|
||||||
include EmailValidatable
|
include EmailValidatable
|
||||||
|
|
||||||
@ -185,6 +187,11 @@ class User < ApplicationRecord
|
|||||||
ldap.delete_attribute(dn,:service)
|
ldap.delete_attribute(dn,:service)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def nostr_pubkey_bech32
|
||||||
|
return nil unless nostr_pubkey.present?
|
||||||
|
Nostr::PublicKey.new(nostr_pubkey).to_bech32
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def ldap
|
def ldap
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
data-settings--nostr-pubkey-pubkey-hex-value="<%= current_user.nostr_pubkey %>">
|
data-settings--nostr-pubkey-pubkey-hex-value="<%= current_user.nostr_pubkey %>">
|
||||||
|
|
||||||
<p class="<%= current_user.nostr_pubkey.present? ? '' : 'hidden' %> mt-2 flex gap-1">
|
<p class="<%= current_user.nostr_pubkey.present? ? '' : 'hidden' %> mt-2 flex gap-1">
|
||||||
<input type="text" value="<%= current_user.nostr_pubkey %>" disabled
|
<input type="text" value="<%= current_user.nostr_pubkey_bech32 %>" disabled
|
||||||
data-settings--nostr-pubkey-target="pubkeyBech32Input"
|
data-settings--nostr-pubkey-target="pubkeyBech32Input"
|
||||||
name="nostr_public_key" class="relative grow" />
|
name="nostr_public_key" class="relative grow" />
|
||||||
<%= link_to nostr_pubkey_settings_path,
|
<%= link_to nostr_pubkey_settings_path,
|
||||||
|
@ -5,5 +5,4 @@ pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
|
|||||||
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
|
pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
|
||||||
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
|
pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
|
||||||
pin_all_from "app/javascript/controllers", under: "controllers"
|
pin_all_from "app/javascript/controllers", under: "controllers"
|
||||||
pin "bech32" # @2.0.0
|
|
||||||
pin "tailwindcss-stimulus-components" # @4.0.3
|
pin "tailwindcss-stimulus-components" # @4.0.3
|
||||||
|
@ -28,7 +28,7 @@ RSpec.describe 'Experimental Settings', type: :feature do
|
|||||||
scenario 'Remove nostr pubkey from account' do
|
scenario 'Remove nostr pubkey from account' do
|
||||||
visit setting_path(:experiments)
|
visit setting_path(:experiments)
|
||||||
expect(page).to have_field("nostr_public_key",
|
expect(page).to have_field("nostr_public_key",
|
||||||
with: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3",
|
with: "npub1qlsc3g0lsl8pw8230w8d9wm6xxcax3f6pkemz5measrmwfxjxteslf2hac",
|
||||||
disabled: true)
|
disabled: true)
|
||||||
|
|
||||||
click_link "Remove"
|
click_link "Remove"
|
||||||
|
@ -205,4 +205,14 @@ RSpec.describe User, type: :model do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#nostr_pubkey_bech32" do
|
||||||
|
before do
|
||||||
|
user.update! nostr_pubkey: "07e188a1ff87ce171d517b8ed2bb7a31b1d3453a0db3b15379ec07b724d232f3"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "encodes the hexadecimal pubkey to bech32" do
|
||||||
|
expect(user.nostr_pubkey_bech32).to eq("npub1qlsc3g0lsl8pw8230w8d9wm6xxcax3f6pkemz5measrmwfxjxteslf2hac")
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
2
vendor/javascript/bech32.js
vendored
2
vendor/javascript/bech32.js
vendored
@ -1,2 +0,0 @@
|
|||||||
var e={};Object.defineProperty(e,"__esModule",{value:true});e.bech32m=e.bech32=void 0;const r="qpzry9x8gf2tvdw0s3jn54khce6mua7l";const t={};for(let e=0;e<r.length;e++){const o=r.charAt(e);t[o]=e}function polymodStep(e){const r=e>>25;return(33554431&e)<<5^996825010&-(r>>0&1)^642813549&-(r>>1&1)^513874426&-(r>>2&1)^1027748829&-(r>>3&1)^705979059&-(r>>4&1)}function prefixChk(e){let r=1;for(let t=0;t<e.length;++t){const o=e.charCodeAt(t);if(o<33||o>126)return"Invalid prefix ("+e+")";r=polymodStep(r)^o>>5}r=polymodStep(r);for(let t=0;t<e.length;++t){const o=e.charCodeAt(t);r=polymodStep(r)^31&o}return r}function convert(e,r,t,o){let n=0;let c=0;const s=(1<<t)-1;const f=[];for(let o=0;o<e.length;++o){n=n<<r|e[o];c+=r;while(c>=t){c-=t;f.push(n>>c&s)}}if(o)c>0&&f.push(n<<t-c&s);else{if(c>=r)return"Excess padding";if(n<<t-c&s)return"Non-zero padding"}return f}function toWords(e){return convert(e,8,5,true)}function fromWordsUnsafe(e){const r=convert(e,5,8,false);if(Array.isArray(r))return r}function fromWords(e){const r=convert(e,5,8,false);if(Array.isArray(r))return r;throw new Error(r)}function getLibraryFromEncoding(e){let o;o="bech32"===e?1:734539939;function encode(e,t,n){n=n||90;if(e.length+7+t.length>n)throw new TypeError("Exceeds length limit");e=e.toLowerCase();let c=prefixChk(e);if("string"===typeof c)throw new Error(c);let s=e+"1";for(let e=0;e<t.length;++e){const o=t[e];if(o>>5!==0)throw new Error("Non 5-bit word");c=polymodStep(c)^o;s+=r.charAt(o)}for(let e=0;e<6;++e)c=polymodStep(c);c^=o;for(let e=0;e<6;++e){const t=c>>5*(5-e)&31;s+=r.charAt(t)}return s}function __decode(e,r){r=r||90;if(e.length<8)return e+" too short";if(e.length>r)return"Exceeds length limit";const n=e.toLowerCase();const c=e.toUpperCase();if(e!==n&&e!==c)return"Mixed-case string "+e;e=n;const s=e.lastIndexOf("1");if(-1===s)return"No separator character for "+e;if(0===s)return"Missing prefix for "+e;const f=e.slice(0,s);const i=e.slice(s+1);if(i.length<6)return"Data too short";let d=prefixChk(f);if("string"===typeof d)return d;const l=[];for(let e=0;e<i.length;++e){const r=i.charAt(e);const o=t[r];if(void 0===o)return"Unknown character "+r;d=polymodStep(d)^o;e+6>=i.length||l.push(o)}return d!==o?"Invalid checksum for "+e:{prefix:f,words:l}}function decodeUnsafe(e,r){const t=__decode(e,r);if("object"===typeof t)return t}function decode(e,r){const t=__decode(e,r);if("object"===typeof t)return t;throw new Error(t)}return{decodeUnsafe:decodeUnsafe,decode:decode,encode:encode,toWords:toWords,fromWordsUnsafe:fromWordsUnsafe,fromWords:fromWords}}e.bech32=getLibraryFromEncoding("bech32");e.bech32m=getLibraryFromEncoding("bech32m");const o=e.__esModule,n=e.bech32m,c=e.bech32;export default e;export{o as __esModule,c as bech32,n as bech32m};
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user