-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit edfadb7
Showing
17 changed files
with
918 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: release github version | ||
on: | ||
push: | ||
tags: | ||
- "[0-9]+.[0-9]+" | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Create GitHub Release | ||
id: create_release | ||
uses: actions/create-release@v1 | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
with: | ||
tag_name: ${{ github.ref }} | ||
release_name: ${{ github.ref }} | ||
draft: false | ||
prerelease: false |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Scrub | ||
|
||
## Automatically forward funds (Scrub) that get paid to the wallet to an LNURLpay or Lightning Address | ||
|
||
SCRUB is a small but handy extension that allows a user to take advantage of all the functionalities inside **LNbits** and upon a payment received to your LNbits wallet, automatically forward it to your desired wallet via LNURL or LNAddress! | ||
|
||
<small>Only whole values, integers, are Scrubbed, amounts will be rounded down (example: 6.3 will be 6)! The decimals, if existing, will be kept in your wallet!</small> | ||
|
||
[**Wallets supporting LNURL**](https://github.com/fiatjaf/awesome-lnurl#wallets) | ||
|
||
## Usage | ||
|
||
1. Create an scrub (New Scrub link)\ | ||
![create scrub](https://i.imgur.com/LUeNkzM.jpg) | ||
|
||
- select the wallet to be _scrubbed_ | ||
- make a small description | ||
- enter either an LNURL pay or a lightning address | ||
|
||
Make sure your LNURL or LNaddress is correct! | ||
|
||
2. A new scrub will show on the _Scrub links_ section\ | ||
![scrub](https://i.imgur.com/LNoFkeu.jpg) | ||
|
||
- only one scrub can be created for each wallet! | ||
- You can _edit_ or _delete_ the Scrub at any time\ | ||
![edit scrub](https://i.imgur.com/Qu65lGG.jpg) | ||
|
||
3. On your wallet, you'll see a transaction of a payment received and another right after it as apayment sent, marked with **#scrubed**\ | ||
![wallet view](https://i.imgur.com/S6EWWCP.jpg) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import asyncio | ||
|
||
from fastapi import APIRouter | ||
from fastapi.staticfiles import StaticFiles | ||
from typing import List | ||
|
||
from lnbits.db import Database | ||
from lnbits.helpers import template_renderer | ||
from lnbits.tasks import catch_everything_and_restart | ||
|
||
db = Database("ext_scrub") | ||
|
||
scheduled_tasks: List[asyncio.Task] = [] | ||
|
||
scrub_static_files = [ | ||
{ | ||
"path": "/scrub/static", | ||
"app": StaticFiles(directory="lnbits/extensions/scrub/static"), | ||
"name": "scrub_static", | ||
} | ||
] | ||
|
||
scrub_ext: APIRouter = APIRouter(prefix="/scrub", tags=["scrub"]) | ||
|
||
|
||
def scrub_renderer(): | ||
return template_renderer(["lnbits/extensions/scrub/templates"]) | ||
|
||
|
||
from .tasks import wait_for_paid_invoices | ||
from .views import * # noqa: F401,F403 | ||
from .views_api import * # noqa: F401,F403 | ||
|
||
|
||
def scrub_start(): | ||
loop = asyncio.get_event_loop() | ||
task = loop.create_task(catch_everything_and_restart(wait_for_paid_invoices)) | ||
scheduled_tasks.append(task) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"name": "Scrub", | ||
"short_description": "Pass payments to LNURLp/LNaddress", | ||
"tile": "/scrub/static/image/scrub.png", | ||
"contributors": ["arcbtc", "talvasconcelos"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
from typing import List, Optional, Union | ||
|
||
from lnbits.helpers import urlsafe_short_hash | ||
|
||
from . import db | ||
from .models import CreateScrubLink, ScrubLink | ||
|
||
|
||
async def create_scrub_link(data: CreateScrubLink) -> ScrubLink: | ||
scrub_id = urlsafe_short_hash() | ||
await db.execute( | ||
""" | ||
INSERT INTO scrub.scrub_links ( | ||
id, | ||
wallet, | ||
description, | ||
payoraddress | ||
) | ||
VALUES (?, ?, ?, ?) | ||
""", | ||
( | ||
scrub_id, | ||
data.wallet, | ||
data.description, | ||
data.payoraddress, | ||
), | ||
) | ||
link = await get_scrub_link(scrub_id) | ||
assert link, "Newly created link couldn't be retrieved" | ||
return link | ||
|
||
|
||
async def get_scrub_link(link_id: str) -> Optional[ScrubLink]: | ||
row = await db.fetchone("SELECT * FROM scrub.scrub_links WHERE id = ?", (link_id,)) | ||
return ScrubLink(**row) if row else None | ||
|
||
|
||
async def get_scrub_links(wallet_ids: Union[str, List[str]]) -> List[ScrubLink]: | ||
if isinstance(wallet_ids, str): | ||
wallet_ids = [wallet_ids] | ||
|
||
q = ",".join(["?"] * len(wallet_ids)) | ||
rows = await db.fetchall( | ||
f""" | ||
SELECT * FROM scrub.scrub_links WHERE wallet IN ({q}) | ||
ORDER BY id | ||
""", | ||
(*wallet_ids,), | ||
) | ||
return [ScrubLink(**row) for row in rows] | ||
|
||
|
||
async def update_scrub_link(link_id: int, **kwargs) -> Optional[ScrubLink]: | ||
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) | ||
await db.execute( | ||
f"UPDATE scrub.scrub_links SET {q} WHERE id = ?", | ||
(*kwargs.values(), link_id), | ||
) | ||
row = await db.fetchone("SELECT * FROM scrub.scrub_links WHERE id = ?", (link_id,)) | ||
return ScrubLink(**row) if row else None | ||
|
||
|
||
async def delete_scrub_link(link_id: int) -> None: | ||
await db.execute("DELETE FROM scrub.scrub_links WHERE id = ?", (link_id,)) | ||
|
||
|
||
async def get_scrub_by_wallet(wallet_id) -> Optional[ScrubLink]: | ||
row = await db.fetchone( | ||
"SELECT * from scrub.scrub_links WHERE wallet = ?", | ||
(wallet_id,), | ||
) | ||
return ScrubLink(**row) if row else None | ||
|
||
|
||
async def unique_scrubed_wallet(wallet_id): | ||
(row,) = await db.fetchone( | ||
"SELECT COUNT(wallet) FROM scrub.scrub_links WHERE wallet = ?", | ||
(wallet_id,), | ||
) | ||
return row |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"repos": [ | ||
{ | ||
"id": "scrub", | ||
"organisation": "lnbits", | ||
"repository": "scrub" | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
async def m001_initial(db): | ||
""" | ||
Initial scrub table. | ||
""" | ||
await db.execute( | ||
""" | ||
CREATE TABLE scrub.scrub_links ( | ||
id TEXT PRIMARY KEY, | ||
wallet TEXT NOT NULL, | ||
description TEXT NOT NULL, | ||
payoraddress TEXT NOT NULL | ||
); | ||
""" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
from sqlite3 import Row | ||
|
||
from pydantic import BaseModel | ||
from starlette.requests import Request | ||
|
||
from lnbits.lnurl import encode as lnurl_encode | ||
|
||
|
||
class CreateScrubLink(BaseModel): | ||
wallet: str | ||
description: str | ||
payoraddress: str | ||
|
||
|
||
class ScrubLink(BaseModel): | ||
id: str | ||
wallet: str | ||
description: str | ||
payoraddress: str | ||
|
||
@classmethod | ||
def from_row(cls, row: Row) -> "ScrubLink": | ||
data = dict(row) | ||
return cls(**data) | ||
|
||
def lnurl(self, req: Request) -> str: | ||
url = req.url_for("scrub.api_lnurl_response", link_id=self.id) | ||
return lnurl_encode(url) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* globals Quasar, Vue, _, VueQrcode, windowMixin, LNbits, LOCALE */ | ||
|
||
Vue.component(VueQrcode.name, VueQrcode) | ||
|
||
var locationPath = [ | ||
window.location.protocol, | ||
'//', | ||
window.location.host, | ||
window.location.pathname | ||
].join('') | ||
|
||
var mapScrubLink = obj => { | ||
obj._data = _.clone(obj) | ||
obj.date = Quasar.utils.date.formatDate( | ||
new Date(obj.time * 1000), | ||
'YYYY-MM-DD HH:mm' | ||
) | ||
obj.amount = new Intl.NumberFormat(LOCALE).format(obj.amount) | ||
obj.print_url = [locationPath, 'print/', obj.id].join('') | ||
obj.pay_url = [locationPath, obj.id].join('') | ||
return obj | ||
} | ||
|
||
new Vue({ | ||
el: '#vue', | ||
mixins: [windowMixin], | ||
data() { | ||
return { | ||
checker: null, | ||
payLinks: [], | ||
payLinksTable: { | ||
pagination: { | ||
rowsPerPage: 10 | ||
} | ||
}, | ||
formDialog: { | ||
show: false, | ||
data: {} | ||
}, | ||
qrCodeDialog: { | ||
show: false, | ||
data: null | ||
} | ||
} | ||
}, | ||
methods: { | ||
getScrubLinks() { | ||
LNbits.api | ||
.request( | ||
'GET', | ||
'/scrub/api/v1/links?all_wallets=true', | ||
this.g.user.wallets[0].inkey | ||
) | ||
.then(response => { | ||
this.payLinks = response.data.map(mapScrubLink) | ||
}) | ||
.catch(err => { | ||
clearInterval(this.checker) | ||
LNbits.utils.notifyApiError(err) | ||
}) | ||
}, | ||
closeFormDialog() { | ||
this.resetFormData() | ||
}, | ||
openUpdateDialog(linkId) { | ||
const link = _.findWhere(this.payLinks, {id: linkId}) | ||
|
||
this.formDialog.data = _.clone(link._data) | ||
this.formDialog.show = true | ||
}, | ||
sendFormData() { | ||
const wallet = _.findWhere(this.g.user.wallets, { | ||
id: this.formDialog.data.wallet | ||
}) | ||
let data = Object.freeze(this.formDialog.data) | ||
console.log(wallet, data) | ||
|
||
if (data.id) { | ||
this.updateScrubLink(wallet, data) | ||
} else { | ||
this.createScrubLink(wallet, data) | ||
} | ||
}, | ||
resetFormData() { | ||
this.formDialog = { | ||
show: false, | ||
data: {} | ||
} | ||
}, | ||
updateScrubLink(wallet, data) { | ||
LNbits.api | ||
.request('PUT', '/scrub/api/v1/links/' + data.id, wallet.adminkey, data) | ||
.then(response => { | ||
this.payLinks = _.reject(this.payLinks, obj => obj.id === data.id) | ||
this.payLinks.push(mapScrubLink(response.data)) | ||
this.formDialog.show = false | ||
this.resetFormData() | ||
}) | ||
.catch(err => { | ||
LNbits.utils.notifyApiError(err) | ||
}) | ||
}, | ||
createScrubLink(wallet, data) { | ||
LNbits.api | ||
.request('POST', '/scrub/api/v1/links', wallet.adminkey, data) | ||
.then(response => { | ||
console.log('RES', response) | ||
this.getScrubLinks() | ||
this.formDialog.show = false | ||
this.resetFormData() | ||
}) | ||
.catch(err => { | ||
LNbits.utils.notifyApiError(err) | ||
}) | ||
}, | ||
deleteScrubLink(linkId) { | ||
var link = _.findWhere(this.payLinks, {id: linkId}) | ||
|
||
LNbits.utils | ||
.confirmDialog('Are you sure you want to delete this pay link?') | ||
.onOk(() => { | ||
LNbits.api | ||
.request( | ||
'DELETE', | ||
'/scrub/api/v1/links/' + linkId, | ||
_.findWhere(this.g.user.wallets, {id: link.wallet}).adminkey | ||
) | ||
.then(response => { | ||
this.payLinks = _.reject(this.payLinks, obj => obj.id === linkId) | ||
}) | ||
.catch(err => { | ||
LNbits.utils.notifyApiError(err) | ||
}) | ||
}) | ||
} | ||
}, | ||
created() { | ||
if (this.g.user.wallets.length) { | ||
var getScrubLinks = this.getScrubLinks | ||
getScrubLinks() | ||
} | ||
} | ||
}) |
Oops, something went wrong.