灵符lingfu
L

ling-wallet

↓ 0 downloads

Ling Wallet: a post-quantum privacy-coin wallet, full node and HyperTorus miner for LNG

Windows · x86-64 ✕Linux · x86-64 ✕LingOS · x86-64LingOS · Pi 5 ARM64 ✕
Keywords wallet, cryptocurrency, lng, node, miner, ling
lingfu install ling-wallet
LicenseMIT
Authorsling-lin
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (116)

ling/ui/icons.ling
# icons.ling — line-art glyphs, spinner, identicons, address fingerprints.

# ~16 px icon, left edge at x, vertically centred on mid.
fn icon_draw(name, x, mid, col) {
    bind y = mid
    if name == "copy" {
        outline(x + 4, mid - 7, 10, 12, col, 1)
        hline(x, mid - 3, 4, col, 1)
        vline(x, mid - 3, 11, col, 1)
        hline(x, mid + 7, 10, col, 1)
        vline(x + 9, mid + 5, 2, col, 1)
    } else if name == "lock" || name == "unlock" {
        outline(x + 1, mid - 2, 14, 10, col, 1)
        fill(x + 7, mid + 1, 2, 4, col)
        bind ly = sel(name == "unlock", 3, 0)
        vline(x + 4, mid - 7 - ly, 5 + ly, col, 1)
        if name == "lock" { vline(x + 11, mid - 7, 5, col, 1) }
        line(x + 4, y - 7 - ly, x + 6, y - 9 - ly, col, 1)
        hline(x + 6, mid - 9 - ly, 4, col, 1)
        line(x + 10, y - 9 - ly, x + 11.5, y - 7 - ly, col, 1)
    } else if name == "in" {
        line(x + 8, y - 8, x + 8, y + 6, col, 1)
        line(x + 3, y + 1, x + 8, y + 6, col, 1)
        line(x + 13, y + 1, x + 8, y + 6, col, 1)
        hline(x + 1, mid + 9, 14, col, 1)
    } else if name == "out" {
        line(x + 8, y + 8, x + 8, y - 6, col, 1)
        line(x + 3, y - 1, x + 8, y - 6, col, 1)
        line(x + 13, y - 1, x + 8, y - 6, col, 1)
        hline(x + 1, mid - 9, 14, col, 1)
    } else if name == "mined" {
        line(x + 8, y - 8, x + 15, y, col, 1)
        line(x + 15, y, x + 8, y + 8, col, 1)
        line(x + 8, y + 8, x + 1, y, col, 1)
        line(x + 1, y, x + 8, y - 8, col, 1)
        line(x + 1, y, x + 15, y, col, 0.6)
        line(x + 8, y - 8, x + 8, y + 8, col, 0.6)
    } else if name == "check" {
        line(x + 2, y, x + 6, y + 4, col, 1)
        line(x + 2, y + 1, x + 6, y + 5, col, 1)
        line(x + 6, y + 4, x + 14, y - 5, col, 1)
        line(x + 6, y + 5, x + 14, y - 4, col, 1)
    } else if name == "warn" {
        line(x + 8, y - 8, x + 16, y + 7, col, 1)
        line(x + 16, y + 7, x, y + 7, col, 1)
        line(x, y + 7, x + 8, y - 8, col, 1)
        fill(x + 7, mid - 3, 2, 6, col)
        fill(x + 7, mid + 4, 2, 2, col)
    } else if name == "shield" {
        line(x + 1, y - 6, x + 8, y - 9, col, 1)
        line(x + 8, y - 9, x + 15, y - 6, col, 1)
        line(x + 15, y - 6, x + 14, y + 2, col, 1)
        line(x + 14, y + 2, x + 8, y + 9, col, 1)
        line(x + 8, y + 9, x + 2, y + 2, col, 1)
        line(x + 2, y + 2, x + 1, y - 6, col, 1)
        line(x + 5, y, x + 7.5, y + 2.5, col, 1)
        line(x + 7.5, y + 2.5, x + 11.5, y - 3, col, 1)
    } else if name == "eye" {
        line(x, y, x + 8, y - 6, col, 1)
        line(x + 8, y - 6, x + 16, y, col, 1)
        line(x + 16, y, x + 8, y + 6, col, 1)
        line(x + 8, y + 6, x, y, col, 1)
        ring(x + 8, y, 2.5, col, 1)
    } else if name == "back" {
        line(x + 12, y - 6, x + 5, y, col, 1)
        line(x + 5, y, x + 12, y + 6, col, 1)
    } else if name == "info" {
        ring(x + 8, y, 7.5, col, 1)
        fill(x + 7, mid - 1, 2, 6, col)
        fill(x + 7, mid - 5, 2, 2, col)
    }
}

# Rotating three-quarter arc.
fn spinner(cx, cy, r, t, col) {
    bind base = t * 5
    bind n = 24
    bind i = 0
    while i < n {
        bind a0 = base + i / n * 4.7
        bind a1 = base + (i + 1) / n * 4.7
        line(cx + cos(a0) * r, cy + sin(a0) * r, cx + cos(a1) * r, cy + sin(a1) * r, col, 0.15 + 0.85 * i / n)
        bind i = i + 1
    }
    ring(cx, cy, r * 0.45, col, 0.35)
}

# Byte i of a hex string.
fn hex_byte(h, i) {
    bind s = substr(h, i * 2, 2)
    if str_len(s) < 2 { return 0 }
    return hex_to_number(s)
}
# Bit k of the little-endian word made of the given four bytes.
fn bit4(b0, b1, b2, b3, k) {
    bind byte = list_get([b0, b1, b2, b3], floor(k / 8))
    return floor(byte / pow(2, k % 8)) % 2
}

# Symmetric 5x5 identicon from an address hash (hex), two ROYGBIV colours,
# solid and crosshatched cells, inside a bracketed tile.
fn identicon(x, y, w, hash) {
    bind ia = hex_byte(hash, 2) % 7
    bind ib = (ia + 2 + hex_byte(hash, 3) % 4) % 7
    bind ca = lift(roygbiv(ia), 0.12)
    bind cb = lift(roygbiv(ib), 0.12)
    fill(x, y, w, w, C_BG_DEEP)
    outline(x, y, w, w, C_LINE_SOFT, 1)
    brackets(x - 1, y - 1, w + 2, w + 2, max(4, floor(w / 6)), ca, 1)
    bind pad = max(3, floor(w / 8))
    bind iw = w - 2 * pad
    bind cell = floor(iw / 5)
    bind ox = x + pad + floor((iw - cell * 5) / 2)
    bind oy = y + pad + floor((iw - cell * 5) / 2)
    bind h0 = hex_byte(hash, 0)
    bind h1 = hex_byte(hash, 1)
    bind h4 = hex_byte(hash, 4)
    bind h5 = hex_byte(hash, 5)
    bind s0 = hex_byte(hash, 6)
    bind s1 = hex_byte(hash, 7)
    bind s2 = hex_byte(hash, 8)
    bind s3 = hex_byte(hash, 9)
    bind any = false
    bind row = 0
    while row < 5 {
        bind col = 0
        while col < 3 {
            bind k = row * 3 + col
            if bit4(h0, h1, h4, h5, k) == 1 {
                bind any = true
                bind solid = bit4(s0, s1, s2, s3, k) == 1
                bind cc = sel(bit4(s0, s1, s2, s3, k + 15) == 1, cb, ca)
                bind side = 0
                while side < 2 {
                    bind cxi = sel(side == 0, col, 4 - col)
                    if side == 0 || cxi != col {
                        bind rx = ox + cxi * cell + 1
                        bind ry = oy + row * cell + 1
                        if solid {
                            fill(rx, ry, cell - 2, cell - 2, shade(cc, 0.1))
                        } else {
                            fill_a(rx, ry, cell - 2, cell - 2, cc, 0.15)
                            cross(rx, ry, cell - 2, cell - 2, cc, 3, 0.9)
                            outline(rx, ry, cell - 2, cell - 2, cc, 0.9)
                        }
                    }
                    bind side = side + 1
                }
            }
            bind col = col + 1
        }
        bind row = row + 1
    }
    if !any { fill(ox + 2 * cell + 1, oy + 2 * cell + 1, cell - 2, cell - 2, ca) }
}

# First 8 bytes of the address hash as four 4-hex groups.
fn fingerprint(hash) {
    return substr(hash, 0, 4) + "-" + substr(hash, 4, 4) + "-" + substr(hash, 8, 4) + "-" + substr(hash, 12, 4)
}

# Fingerprint in mono with a colour tick under each group; returns the width.
fn draw_fingerprint(x, base, size, fp, col) {
    bind px = x
    bind groups = str_split(fp, "-")
    bind i = 0
    while i < len(groups) {
        bind g = list_get(groups, i)
        bind w = round(t_text(F_MONO, size, px, base, g, col))
        fill(px, base + 4, w, 2, shade(roygbiv(hex_to_number(g) % 7), 0.15))
        bind px = px + w
        if i + 1 < len(groups) {
            fill(px + 6, base - round(size * 0.22), 3, 3, C_TEXT_FAINT)
            bind px = px + 15
        }
        bind i = i + 1
    }
    return px - x
}

# Group an address in 4-char chunks, `per_line` groups per line.
fn grouped(s, per_line) {
    bind lines = []
    bind cur = ""
    bind n = 0
    bind i = 0
    while i < str_len(s) {
        bind g = substr(s, i, 4)
        bind cur = sel(cur == "", g, cur + " " + g)
        bind n = n + 1
        if n == per_line {
            bind lines = list_push(lines, cur)
            bind cur = ""
            bind n = 0
        }
        bind i = i + 4
    }
    if cur != "" { bind lines = list_push(lines, cur) }
    return lines
}

# "lng1q8w3x5ff…4sa8gu" style shortening.
fn short_mid(s, head, tail) {
    if str_len(s) <= head + tail + 1 { return s }
    return substr(s, 0, head) + "…" + substr(s, str_len(s) - tail, tail)
}

← Back to index