LBRY Web Wallet initial commit (with some DeSo code still left over)

This commit is contained in:
Daniel Krol 2022-04-08 11:27:09 -04:00
commit 169e223cb6
272 changed files with 98622 additions and 0 deletions

17
.browserslistrc Normal file
View file

@ -0,0 +1,17 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.

16
.editorconfig Normal file
View file

@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

46
.gitignore vendored Normal file
View file

@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

1
.npmrc Normal file
View file

@ -0,0 +1 @@
ignore-scripts = true

2
CODEOWNERS Normal file
View file

@ -0,0 +1,2 @@
# For now, tag everyone who wants to participate
* @deso-protocol/reviewers

46
Caddyfile Normal file
View file

@ -0,0 +1,46 @@
# Global caddy config options must be first
{
admin off
auto_https off
}
# Bind to port 82
:82
# Serve static files
file_server
# Fallback to index.html for everything but assets
@html {
not path *.js *.css *.png *.svg *.ttf *.woff2
file index.html
}
handle_errors {
header Cache-Control no-store
}
rewrite @html {http.matchers.file.relative}
# Don't cache index.html and set CSP
header @html Cache-Control no-store
header @html Content-Security-Policy "
default-src 'self';
connect-src
{$DOMAIN:https://node.deso.org}/api/v0/get-users-stateless
{$DOMAIN:https://node.deso.org}/api/v0/get-app-state
{$DOMAIN:https://node.deso.org}/api/v0/get-referral-info-for-referral-hash
{$DOMAIN:https://node.deso.org}/api/v0/get-user-derived-keys
{$DOMAIN:https://node.deso.org}/api/v0/get-transaction-spending
{$DOMAIN:https://node.deso.org}/api/v0/send-phone-number-verification-text
{$DOMAIN:https://node.deso.org}/api/v0/submit-phone-number-verification-code
img-src 'self'
{$DOMAIN:https://node.deso.org}/api/v0/get-single-profile-picture/;
style-src 'self' 'unsafe-inline'
https://fonts.googleapis.com
https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css;
font-src 'self'
https://fonts.googleapis.com
https://fonts.gstatic.com
https://ka-f.fontawesome.com;"

43
Dockerfile Normal file
View file

@ -0,0 +1,43 @@
FROM node:14.15.5-alpine3.13 AS identity
WORKDIR /identity
RUN apk add git
COPY ./package.json .
COPY ./package-lock.json .
COPY ./.npmrc .
# use yarn to upgrade npm
RUN yarn global add npm@7
# install frontend dependencies before copying the frontend code
# into the container so we get docker cache benefits
RUN npm install
# don't allow any dependencies with vulnerabilities
#RUN npx audit-ci --low
# running ngcc before build_prod lets us utilize the docker
# cache and significantly speeds up builds without requiring us
# to import/export the node_modules folder from the container
RUN npm run ngcc
COPY ./angular.json .
COPY ./tsconfig.json .
COPY ./tsconfig.app.json .
COPY ./webpack.config.js .
COPY ./tslint.json .
COPY ./src ./src
RUN npm run build_prod
# build minified version of frontend, served using caddy
FROM caddy:2.3.0-alpine
WORKDIR /identity
COPY ./Caddyfile .
COPY --from=identity /identity/dist/identity .
ENTRYPOINT ["caddy", "run"]

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 DeSo Community Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

17
README.md Normal file
View file

@ -0,0 +1,17 @@
Forked from https://github.com/deso-protocol/identity though most of it is gutted.
# LBRY Web Wallet
LBRY Web Wallet service
## Development server
Run `npm start` for a dev server (this adds extra setup on top of mere `ng serve`). Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
After proper configuration of `environment.ts` and `environment.prod.ts`, run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.

137
angular.json Normal file
View file

@ -0,0 +1,137 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"identity": {
"projectType": "application",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
},
"@schematics/angular:application": {
"strict": true
}
},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"outputPath": "dist/identity",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": true,
"assets": [
"src/favicon.ico",
"src/assets",
"src/vendor"
],
"styles": [
"./node_modules/intl-tel-input/build/css/intlTelInput.css",
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
],
"scripts": [],
"customWebpackConfig": {
"path": "./webpack.config.js"
}
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "2.5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
]
}
}
},
"serve": {
"builder": "@angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "identity:build"
},
"configurations": {
"production": {
"browserTarget": "identity:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-builders/custom-webpack:extract-i18n",
"options": {
"browserTarget": "identity:build"
}
},
"test": {
"builder": "@angular-bulders/custom-webpack:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "identity:serve"
},
"configurations": {
"production": {
"devServerTarget": "identity:serve:production"
}
}
}
}
}
},
"defaultProject": "identity"
}

37
e2e/protractor.conf.js Normal file
View file

@ -0,0 +1,37 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
browserName: 'chrome'
},
directConnect: true,
SELENIUM_PROMISE_MANAGER: false,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({
spec: {
displayStacktrace: StacktraceOption.PRETTY
}
}));
}
};

23
e2e/src/app.e2e-spec.ts Normal file
View file

@ -0,0 +1,23 @@
import { browser, logging } from 'protractor';
import { AppPage } from './app.po';
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display welcome message', async () => {
await page.navigateTo();
expect(await page.getTitleText()).toEqual('identity app is running!');
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry));
});
});

11
e2e/src/app.po.ts Normal file
View file

@ -0,0 +1,11 @@
import { browser, by, element } from 'protractor';
export class AppPage {
async navigateTo(): Promise<unknown> {
return browser.get(browser.baseUrl);
}
async getTitleText(): Promise<string> {
return element(by.css('app-root .content span')).getText();
}
}

13
e2e/tsconfig.json Normal file
View file

@ -0,0 +1,13 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/e2e",
"module": "commonjs",
"target": "es2018",
"types": [
"jasmine",
"node"
]
}
}

7
example/README.md Normal file
View file

@ -0,0 +1,7 @@
This is an example app that communicates with the web wallet. It's also an angular app (for now).
Forked from https://github.com/deso-protocol/identity though most of it is gutted.
WIP. Still gutting DeSo, noting which parts we might need ourselves later, and which parts we should put our own stuff in its place.
TODO - instructions for running backend and frontend, in their own READMEs. And refer to both from this README. I'd do both here, but the frontend is angular, which has its own instructions already. Backend instructions should include running lbrycrd mainnet with `./lbrycrdd -server -noconnect`.

2
example/backend/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
/config.go
/main

11
example/backend/go.mod Normal file
View file

@ -0,0 +1,11 @@
module orblivion/deso-demo-server
go 1.17
require github.com/d4l3k/go-electrum v0.0.0-20180417061451-65385de82759
require (
github.com/btcsuite/btcd v0.20.1-beta // indirect
github.com/btcsuite/btcutil v1.0.2 // indirect
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d // indirect
)

40
example/backend/go.sum Normal file
View file

@ -0,0 +1,40 @@
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts=
github.com/btcsuite/btcutil v1.0.2/go.mod h1:j9HUFwoQRsZL3V4n+qG+CUnEGHOarIxfC3Le2Yhbcts=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/d4l3k/go-electrum v0.0.0-20180417061451-65385de82759 h1:DEb1Cz/qxsLbpxLXCjyq6bivsgAe6ECrL7QoWoFLGpk=
github.com/d4l3k/go-electrum v0.0.0-20180417061451-65385de82759/go.mod h1:1bcGG6FX+aD2ZMeAemoEh98vG/WotuJ3kbF+w47YLQQ=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495 h1:6IyqGr3fnd0tM3YxipK27TUskaOVUjU2nG45yzwcQKY=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d h1:2+ZP7EfsZV7Vvmx3TIqSlSzATMkTAKqM14YGFPoSKjI=
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

277
example/backend/main.go Normal file
View file

@ -0,0 +1,277 @@
package main
import (
"bytes"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"log"
"net/http"
"os/exec"
"path"
"strings"
"github.com/d4l3k/go-electrum/electrum"
)
// NOTE: This was initially hacked together for a demo. It doesn't do proper
// error checking etc. If this comment is still here it's probably not ready
// yet.
const PathBroadcastTransaction = "/transaction/broadcast"
const PathDecodeTransaction = "/transaction/decode"
const PathPSBT = "/transaction/psbt"
var LBRYCRD = path.Join(LBRYCRD_PATH, "lbrycrd-cli")
var node *electrum.Node
func getUnspentForAmount(
outputAddress string,
desiredAmount float64,
) (inputs []*electrum.Transaction, totalAmount float64, enough bool) {
unspent, _ := node.BlockchainAddressListUnspent(outputAddress)
for _, u := range unspent {
if desiredAmount > totalAmount {
totalAmount += float64(u.Value) / 100000000.0
inputs = append(inputs, u)
}
}
if desiredAmount <= totalAmount {
enough = true
}
return
}
func makePsbt(inputs []*electrum.Transaction, outputAddress string, amount float64) (string, error) {
var inputTxnParts []string
for _, input := range inputs {
inputTxnParts = append(
inputTxnParts,
fmt.Sprintf(`{"txid": "%s", "vout": %d}`, input.Hash, input.Pos),
)
}
var inputTxnsParam = "[" + strings.Join(inputTxnParts, ", ") + "]"
var outputAddressesParam = fmt.Sprintf(`[{"%s": %f}]`, outputAddress, amount)
var out bytes.Buffer
var errOut bytes.Buffer
fmt.Println(LBRYCRD, "createpsbt", string(inputTxnsParam), string(outputAddressesParam))
cmd := exec.Command(LBRYCRD, "createpsbt", string(inputTxnsParam), string(outputAddressesParam))
cmd.Stdout = &out
cmd.Stderr = &errOut
err := cmd.Run()
if err != nil {
fmt.Println(err.Error())
fmt.Println(out.String())
fmt.Println(errOut.String())
return "", err
} else {
psbtBytes, err := base64.StdEncoding.DecodeString(out.String())
if err != nil {
fmt.Println(err.Error())
}
return hex.EncodeToString(psbtBytes), nil
}
}
func decodeTransaction(txn string) (decoded string, err error) {
var out bytes.Buffer
var errOut bytes.Buffer
cmd := exec.Command(LBRYCRD, "decoderawtransaction", txn)
cmd.Stdout = &out
cmd.Stderr = &errOut
err = cmd.Run()
if err != nil {
err = fmt.Errorf(err.Error() + "\n" + out.String() + "\n" + errOut.String())
} else {
decoded = out.String()
}
return
}
func generateBlockRegtest() (cmdOut string, err error) {
var out bytes.Buffer
var errOut bytes.Buffer
cmd := exec.Command(LBRYCRD, "generate", "1")
cmd.Stdout = &out
cmd.Stderr = &errOut
err = cmd.Run()
if err != nil {
err = fmt.Errorf(err.Error() + "\n" + out.String() + "\n" + errOut.String())
} else {
cmdOut = out.String()
}
return
}
func main() {
// TODO Throw error if lbrycrdd is not running on mainnet
node = electrum.NewNode()
if err := node.ConnectTCP(ELECTRUM_SERVER); err != nil {
log.Fatal(err)
}
http.HandleFunc(PathBroadcastTransaction, broadcastTransaction)
http.HandleFunc(PathDecodeTransaction, getDecodedTransaction)
http.HandleFunc(PathPSBT, getPSBT)
fmt.Println("Serving at :8090")
http.ListenAndServe(":8090", nil)
}
type BroadcastTransactionRequest struct {
TransactionHex string `json:"transactionHex"`
}
type DecodeTransactionRequest struct {
TransactionHex string `json:"transactionHex"`
}
type PSBTRequest struct {
ToAddress string `json:"toAddress"`
FromAddress string `json:"fromAddress"`
DesiredAmount float64 `json:"desiredAmount"`
}
type PSBTResponse struct {
NonWitnessUtxoHexes []string `json:"nonWitnessUtxoHex"`
PSBTHex string `json:"psbtHex"`
Error string `json:"error"`
ActualAmount float64 `json:"actualAmount"`
}
func getPSBT(w http.ResponseWriter, req *http.Request) {
var psbtr PSBTRequest
var pr PSBTResponse
if err := json.NewDecoder(req.Body).Decode(&psbtr); err != nil {
http.Error(w, string("Malformed request body JSON"), http.StatusBadRequest)
return
}
w.Header().Set("Access-Control-Allow-Origin", CORS)
outputs, actualAmount, success := getUnspentForAmount(psbtr.FromAddress, psbtr.DesiredAmount)
if !success {
pr = PSBTResponse{Error: "Not enough funds"}
response, _ := json.Marshal(pr)
fmt.Fprintf(w, string(response))
return
}
// Doing the `desiredAmount` so that the remainder can go to fees. This
// might lead to super high fees but the server would stop us from
// broadcasting it. If we used `actualAmount`, we'd have zero fees. If we
// used `actualAmount` minus fees, it might be way more than `desiredAmount`
// and the server *wouldn't* stop us from broadcasting.
psbt, err := makePsbt(outputs, psbtr.ToAddress, psbtr.DesiredAmount)
if err != nil {
pr = PSBTResponse{Error: "getPsbt - err: " + err.Error()}
response, _ := json.Marshal(pr)
http.Error(w, string(response), http.StatusInternalServerError)
return
}
var fullTxns []string
for _, output := range outputs {
fullTxn, err := node.BlockchainTransactionGet(output.Hash)
if err != nil {
pr = PSBTResponse{Error: "getPsbt - err: " + err.Error()}
response, _ := json.Marshal(pr)
http.Error(w, string(response), http.StatusInternalServerError)
return
}
fullTxns = append(fullTxns, fullTxn)
}
pr = PSBTResponse{
NonWitnessUtxoHexes: fullTxns,
PSBTHex: psbt,
ActualAmount: actualAmount,
}
// TODO - is this check future-proof enough? (change in prices, etc)
if actualAmount-psbtr.DesiredAmount > 0.01 {
pr.Error = "Absurdly high fee"
}
response, _ := json.Marshal(pr)
fmt.Fprintf(w, string(response))
fmt.Println("get psbt")
}
type BroadcastTransactionResponse struct {
Txid string `json:"txid"`
}
func broadcastTransaction(w http.ResponseWriter, req *http.Request) {
var btr BroadcastTransactionRequest
if err := json.NewDecoder(req.Body).Decode(&btr); err != nil {
http.Error(w, string("Malformed request body JSON"), http.StatusBadRequest)
return
}
// TODO need some sort of actual feedback for web app for errors
w.Header().Set("Access-Control-Allow-Origin", CORS)
broadcastResult, err := node.BlockchainTransactionBroadcast([]byte(btr.TransactionHex))
if err != nil {
fmt.Println("broadcast failure")
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
broadcastResultStr := fmt.Sprintf("+v", broadcastResult)
btresp := BroadcastTransactionResponse{Txid: broadcastResultStr}
response, _ := json.Marshal(btresp)
fmt.Fprintf(w, string(response))
fmt.Println("broadcast success:\n" + broadcastResultStr)
return
}
type DecodeTransactionResponse struct {
DecodedTransaction string `json:"decodedTransaction"`
}
func getDecodedTransaction(w http.ResponseWriter, req *http.Request) {
var dtr DecodeTransactionRequest
if err := json.NewDecoder(req.Body).Decode(&dtr); err != nil {
http.Error(w, string("Malformed request body JSON"), http.StatusBadRequest)
return
}
// TODO need some sort of actual feedback for web app for errors
w.Header().Set("Access-Control-Allow-Origin", CORS)
decodedTransaction, err := decodeTransaction(dtr.TransactionHex)
if err != nil {
fmt.Println("decode failure")
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
dtresp := DecodeTransactionResponse{
DecodedTransaction: decodedTransaction,
}
response, _ := json.Marshal(dtresp)
fmt.Fprintf(w, string(response))
fmt.Printf(decodedTransaction)
fmt.Println("decode success")
return
}

8
example/backend/runandwatch.sh Executable file
View file

@ -0,0 +1,8 @@
#!/bin/bash
# mainly because the electrum https calls seems to crash a fair amount
until go run .; do
echo "Backend crashed with exit code $?. Respawning.." >&2
sleep 1
done

View file

@ -0,0 +1,13 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = off
trim_trailing_whitespace = false

View file

@ -0,0 +1,36 @@
{
"root": true,
"ignorePatterns": ["projects/**/*"],
"overrides": [
{
"files": ["*.ts"],
"parserOptions": {
"project": ["tsconfig.json", "e2e/tsconfig.json"],
"createDefaultProgram": true
},
"extends": [
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates",
"plugin:prettier/recommended"
],
"rules": {}
},
// NOTE: WE ARE NOT APPLYING PRETTIER IN THIS OVERRIDE, ONLY @ANGULAR-ESLINT/TEMPLATE
{
"files": ["*.html"],
"extends": ["plugin:@angular-eslint/template/recommended"],
"rules": {}
},
// NOTE: WE ARE NOT APPLYING @ANGULAR-ESLINT/TEMPLATE IN THIS OVERRIDE, ONLY PRETTIER
{
"files": ["*.html"],
"excludedFiles": ["*inline-template-*.component.html"],
"extends": ["plugin:prettier/recommended"],
"rules": {
// NOTE: WE ARE OVERRIDING THE DEFAULT CONFIG TO ALWAYS SET THE PARSER TO ANGULAR (SEE BELOW)
"prettier/prettier": ["error", { "parser": "angular" }]
}
}
]
}

46
example/frontend/.gitignore vendored Normal file
View file

@ -0,0 +1,46 @@
# See http://help.github.com/ignore-files/ for more about ignoring files.
# compiled output
/dist
/tmp
/out-tsc
# Only exists if Bazel was run
/bazel-out
# dependencies
/node_modules
# profiling files
chrome-profiler-events.json
speed-measure-plugin.json
# IDEs and editors
/.idea
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# IDE - VSCode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# misc
/.sass-cache
/connect.lock
/coverage
/libpeerconnection.log
npm-debug.log
yarn-error.log
testem.log
/typings
# System Files
.DS_Store
Thumbs.db

View file

@ -0,0 +1,24 @@
# Commands to start on workspace startup
tasks:
- name: open terminial
- name: install & run dev server
openMode: split-right
init: npm install
command: npm start
# Pre-install some extensions
vscode:
extensions:
- angular.ng-template
- ecmel.vscode-html-css
- eamodio.gitlens
# Ports to expose on workspace startup
ports:
- port: 4200
onOpen: open-browser
# Github integration
github:
prebuilds:
master: true

1
example/frontend/.npmrc Normal file
View file

@ -0,0 +1 @@
ignore-scripts = true

View file

@ -0,0 +1,7 @@
{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"quoteProps": "as-needed",
"htmlWhitespaceSensitivity": "ignore",
}

View file

@ -0,0 +1,2 @@
# For now, tag everyone who wants to participate
* @deso-protocol/reviewers

View file

@ -0,0 +1,92 @@
# Global caddy config options must be first
{
admin off
auto_https off
}
# Bind to port 80
:80
# Serve static files
file_server
# Fallback to index.html for everything but assets
@html {
not path *.js *.css *.png *.jpg *.svg *.pdf *.eot *.ttf *.woff *.woff2 *.webmanifest
file index.html
}
handle_errors {
header Cache-Control no-store
}
rewrite @html {http.matchers.file.relative}
# Don't cache index.html and set CSP
header @html Cache-Control no-store
header @html Content-Security-Policy "
default-src 'self';
connect-src 'self'
node.deso.org
amp.deso.org
bithunt.deso.org
bitclout.com:*
api.bitclout.com
bithunt.bitclout.com
https://altumbase.com
localhost:*
explorer.bitclout.com
https://api.blockchain.com/ticker
https://api.blockchain.com/mempool/fees
https://ka-f.fontawesome.com/
bitcoinfees.earn.com
api.blockcypher.com
amp.bitclout.com
api.testwyre.com
api.sendwyre.com
https://videodelivery.net
https://upload.videodelivery.net;
script-src 'self'
https://kit.fontawesome.com/070ca4195b.js
https://ka-f.fontawesome.com/;
style-src 'self'
'unsafe-inline'
https://fonts.googleapis.com
https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css;
img-src 'self'
data:
i.imgur.com
images.deso.org
images.bitclout.com
quickchart.io
arweave.net
*.arweave.net
*.pearl.app
cloudflare-ipfs.com;
font-src 'self'
https://fonts.googleapis.com
https://fonts.gstatic.com
https://ka-f.fontawesome.com;
frame-src 'self'
localhost:*
identity.deso.org
identity.deso.blue
identity.deso.green
identity.bitclout.com
identity.bitclout.blue
identity.bitclout.green
https://geo.captcha-delivery.com
https://www.youtube.com
https://youtube.com
https://player.vimeo.com
https://www.tiktok.com
https://giphy.com
https://open.spotify.com
https://w.soundcloud.com
https://player.twitch.tv
https://clips.twitch.tv
pay.testwyre.com
pay.sendwyre.com
https://iframe.videodelivery.net;
frame-ancestors 'self';"

View file

@ -0,0 +1,60 @@
FROM node:14.15.5-alpine3.13 AS frontend
WORKDIR /frontend
# install git
RUN apk add git
# use yarn to upgrade npm
RUN yarn global add npm@7
COPY ./package.json .
COPY ./package-lock.json .
COPY ./.npmrc .
# install frontend dependencies before copying the frontend code
# into the container so we get docker cache benefits
RUN npm install
# don't allow any dependencies with vulnerabilities
#RUN npx audit-ci --low
# running ngcc before build_prod lets us utilize the docker
# cache and significantly speeds up builds without requiring us
# to import/export the node_modules folder from the container
RUN npm run ngcc
COPY ./angular.json .
COPY ./tsconfig.json .
COPY ./src ./src
# use --build-arg index=index.custom.html to specify a custom index.html file
ARG index=index.html
# overwrite default index file with custom file
COPY ./src/$index ./src/index.html
# use --build-arg environment=custom to specify a custom environment
ARG environment=prod
# overwrite default environment file with custom file
COPY ./src/environments/environment.$environment.ts ./src/environments/environment.prod.ts
RUN npm run build_prod
# build minified version of frontend, served using caddy
FROM caddy:2.3.0-alpine
WORKDIR /frontend
COPY ./Caddyfile .
COPY --from=frontend /frontend/dist .
# We use a run.sh script so that we can pass environment variables
# to it.
COPY ./run.sh .
# Default options overrideable by docker-compose
ENV CADDY_FILE "/frontend/Caddyfile"
ENTRYPOINT ["/frontend/run.sh"]

21
example/frontend/LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 DeSo Community Developers
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,34 @@
![DeSo Logo](src/assets/deso/camelcase_logo.svg)
# About DeSo
DeSo is a blockchain built from the ground up to support a fully-featured
social network. Its architecture is similar to Bitcoin, only it supports complex
social network data like profiles, posts, follows, creator coin transactions, and
more.
[Read about the vision](https://docs.deso.org/#the-ultimate-vision)
# About This Repo
Documentation for this repo lives on docs.deso.org. Specifically, the following
docs should give you everything you need to get started:
* [DeSo Code Walkthrough](https://docs.deso.org/code/walkthrough)
* [Setting Up Your Dev Environment](https://docs.deso.org/code/dev-setup)
* [Making Your First Changes](https://docs.deso.org/code/making-your-first-changes)
# Start Coding
The quickest way to contribute changes to the BitClout Frontend is the following these steps:
1. Open frontend repo in Gitpod
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/deso-protocol/frontend)
You can use any repo / branch URL and just prepend `https://gitpod.io/#` to it.
2. If needed, login to your github account
3. Set the correct `lastLocalNodeV2` to `"https://api.tijn.club"` in your browser Local Storage for the gitpod preview URL
4. Create a new branch to start working
To commit / submit a pull reqest from gitpod, you will need to give gitpod additional permissions to your github account: `public_repo, read:org, read:user, repo, user:email, workflow` which you can do on the [GitPod Integrations page](https://gitpod.io/integrations).

View file

@ -0,0 +1,149 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"cli": {
"analytics": false
},
"version": 1,
"newProjectRoot": "projects",
"projects": {
"deso-frontend": {
"root": "",
"sourceRoot": "src",
"projectType": "application",
"prefix": "app",
"schematics": {
"@schematics/angular:component": {
"style": "scss"
}
},
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"aot": true,
"outputPath": "dist",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"assets": [
"src/assets",
"src/vendor"
],
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"./node_modules/ngx-toastr/toastr.css",
"src/styles.scss",
"src/styles.sass"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "20mb",
"maximumError": "20mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "deso-frontend:build"
},
"configurations": {
"production": {
"browserTarget": "deso-frontend:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "deso-frontend:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"./node_modules/ngx-toastr/toastr.css",
"src/styles.scss",
"src/styles.sass"
],
"scripts": [],
"assets": [
"src/assets"
]
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
}
}
},
"deso-frontend-e2e": {
"root": "e2e/",
"projectType": "application",
"prefix": "",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "deso-frontend:serve"
},
"configurations": {
"production": {
"devServerTarget": "deso-frontend:serve:production"
}
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"e2e//**/*.ts",
"e2e//**/*.html"
]
}
}
}
}
},
"defaultProject": "deso-frontend"
}

View file

@ -0,0 +1,45 @@
{
"extends": "../.eslintrc.json",
"ignorePatterns": [
"!**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"parserOptions": {
"project": [
"e2e//tsconfig.app.json",
"e2e//tsconfig.spec.json",
"e2e//e2e/tsconfig.json"
],
"createDefaultProgram": true
},
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "",
"style": "kebab-case"
}
]
}
},
{
"files": [
"*.html"
],
"rules": {}
}
]
}

View file

@ -0,0 +1,28 @@
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./src/**/*.e2e-spec.ts'
],
capabilities: {
'browserName': 'chrome'
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
print: function() {}
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.e2e.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};

View file

@ -0,0 +1,25 @@
import { AppPage } from "./app.po";
import { browser, logging } from "protractor";
describe("workspace-project App", () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it("should display welcome message", () => {
page.navigateTo();
expect(page.getTitleText()).toEqual("Welcome to electron-angular-app!");
});
afterEach(async () => {
// Assert that there are no errors emitted from the browser
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
expect(logs).not.toContain(
jasmine.objectContaining({
level: logging.Level.SEVERE,
} as logging.Entry)
);
});
});

View file

@ -0,0 +1,11 @@
import { browser, by, element } from "protractor";
export class AppPage {
navigateTo() {
return browser.get(browser.baseUrl) as Promise<any>;
}
getTitleText() {
return element(by.css("app-root h1")).getText() as Promise<string>;
}
}

View file

@ -0,0 +1,13 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"module": "commonjs",
"target": "es5",
"types": [
"jasmine",
"jasminewd2",
"node"
]
}
}

49578
example/frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
{
"name": "deso-frontend",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"generate": "ng generate",
"test": "ng test",
"lint": "ng lint --fix",
"e2e": "ng e2e",
"build_prod": "ng build --prod --base-href / --deploy-url /",
"ngcc": "ngcc --properties es2015"
},
"browserslist": [
"> 5%"
],
"private": true,
"dependencies": {
"@angular/animations": "~11.2.12",
"@angular/cdk": "^11.2.11",
"@angular/common": "^11.2.12",
"@angular/compiler": "^11.1.2",
"@angular/forms": "^11.2.12",
"@angular/material": "^11.2.11",
"@angular/platform-browser": "^11.2.12",
"@angular/platform-browser-dynamic": "^11.2.12",
"@angular/router": "^11.2.12",
"@ethereumjs/common": "^2.5.0",
"@ethereumjs/tx": "^3.3.2",
"@ethereumjs/vm": "^5.5.3",
"amplitude-js": "^7.4.3",
"assert": "^2.0.0",
"autolinker": "^3.14.2",
"bs58": "^4.0.1",
"canvas-confetti": "^1.3.0",
"cipher-base": "^1.0.4",
"confetti-js": "github:deso-protocol/confetti-js",
"core-js": "^2.5.4",
"crypto": "^1.0.1",
"crypto-browserify": "^3.12.0",
"currency-symbol-map": "^5.0.1",
"ethereumjs-tx": "^2.1.2",
"ethereumjs-util": "^7.1.2",
"fs": "0.0.1-security",
"google-libphonenumber": "^3.2.16",
"hash-base": "^3.0.4",
"https-browserify": "^1.0.0",
"is-buffer": "^2.0.4",
"lodash": "^4.17.15",
"ng2-animate-on-scroll": "^2.2.1",
"ngx-bootstrap": "^6.2.0",
"ngx-toastr": "^13.2.0",
"ngx-ui-scroll": "^2.0.0-rc.8",
"os-browserify": "^0.3.0",
"pulltorefreshjs": "^0.1.22",
"rxjs": "~6.6.3",
"rxjs-compat": "^6.6.3",
"sprintf-js": "^1.1.2",
"stream": "0.0.2",
"stream-browserify": "^3.0.0",
"stream-http": "^3.2.0",
"stream-transform": "^1.0.8",
"sweetalert2": "^10.15.5",
"tslib": "^2.0.0",
"tus-js-client": "^2.3.0",
"underscore": "^1.9.1",
"web3": "^1.6.0",
"webpack": "^4.41.2",
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1102.11",
"@angular-devkit/build-ng-packagr": "~0.1002.1",
"@angular-eslint/builder": "4.2.0",
"@angular-eslint/eslint-plugin": "4.2.0",
"@angular-eslint/eslint-plugin-template": "4.2.0",
"@angular-eslint/schematics": "4.2.0",
"@angular-eslint/template-parser": "4.2.0",
"@angular/cli": "^11.2.11",
"@angular/compiler-cli": "~11.2.12",
"@angular/core": "^11.2.12",
"@angular/language-service": "~11.2.12",
"@types/amplitude-js": "^7.0.1",
"@types/jasmine": "^2.8.16",
"@types/jasminewd2": "~2.0.3",
"@types/jest": "^26.0.23",
"@types/lodash": "^4.14.168",
"@types/node": "~8.9.4",
"@types/sprintf-js": "^1.1.2",
"@types/underscore": "^1.11.2",
"@typescript-eslint/eslint-plugin": "4.16.1",
"@typescript-eslint/parser": "4.16.1",
"audit-ci": "^4.0.0",
"eslint": "^7.6.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^3.4.0",
"jasmine-core": "~3.5.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "^6.3.2",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage-istanbul-reporter": "~3.0.2",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"ng-packagr": "^11.1.2",
"prettier": "^2.2.1",
"protractor": "~7.0.0",
"ts-node": "~7.0.0",
"typescript": "^4.0.7",
"webpack-cli": "^3.3.10"
},
"main": "main.js"
}

5
example/frontend/run.sh Executable file
View file

@ -0,0 +1,5 @@
#!/bin/sh
echo "Loading Caddy config from file: ${CADDY_FILE}"
caddy run --config ${CADDY_FILE}

View file

@ -0,0 +1,16 @@
import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";
import { SpendLBCComponent } from "./spend-lbc/spend-lbc.component";
const routes: Routes = [
{ path: "", component: SpendLBCComponent, pathMatch: "full" },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
class AppRoutingModule {}
export { AppRoutingModule };

View file

@ -0,0 +1,14 @@
<!--Desktop menu-->
<!-- Identity service / storage access request -->
<iframe
id="identity"
[src]="identityService.sanitizedIdentityServiceURL"
frameborder="0"
class="global__iframe"
[style.display]="globalVars.browserSupported ? 'none' : 'block'"
></iframe>
<!--p-0 is important here. Mobile UIs expect that there's no side padding.-->
<div *ngIf="globalVars.browserSupported">
<router-outlet></router-outlet>
</div>

View file

@ -0,0 +1,35 @@
#my-canvas-0 {
position: fixed;
z-index: 2000;
height: 100%;
width: 100%;
pointer-events: none;
}
#my-canvas-1 {
position: fixed;
z-index: 2000;
height: 100%;
width: 100%;
pointer-events: none;
}
#my-canvas-2 {
position: fixed;
z-index: 2000;
height: 100%;
width: 100%;
pointer-events: none;
}
#my-canvas-3 {
position: fixed;
z-index: 2000;
height: 100%;
width: 100%;
pointer-events: none;
}
#my-canvas-4 {
position: fixed;
z-index: 2000;
height: 100%;
width: 100%;
pointer-events: none;
}

View file

@ -0,0 +1,63 @@
import { Component, OnInit } from "@angular/core";
import { BackendApiService } from "./backend-api.service";
import { GlobalVarsService } from "./global-vars.service";
import { IdentityService } from "./identity.service";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"],
})
export class AppComponent implements OnInit {
constructor(
private backendApi: BackendApiService,
public globalVars: GlobalVarsService,
public identityService: IdentityService,
) {
this.globalVars.Init(
null, // loggedInUser
[], // userList TODO - accountList? If we do this.
);
// Nuke the referrer so we don't leak anything
// We also have a meta tag in index.html that does this in a different way to make
// sure it's nuked.
//
//
// TODO: I'm pretty sure all of this could fail on IE so we should make sure people
// only use the app with chrome.
Object.defineProperty(document, "referrer", {
get() {
return "";
},
});
Object.defineProperty(document, "referer", {
get() {
return "";
},
});
}
ngOnInit() {
this.identityService.info().subscribe((res) => {
// If the browser is not supported, display the browser not supported screen.
if (res.browserSupported) {
this.globalVars.browserSupported = true;
this.loadApp();
}
});
}
// TODO Plug LBRY accounts into local storage
loadApp() {
this.identityService.identityServiceUsers = this.backendApi.GetStorage(this.backendApi.IdentityUsersKey) || {};
// Filter out invalid public keys
const publicKeys = Object.keys(this.identityService.identityServiceUsers);
for (const publicKey of publicKeys) {
if (!publicKey.match(/^[a-zA-Z0-9]{54,55}$/)) {
delete this.identityService.identityServiceUsers[publicKey];
}
}
this.backendApi.SetStorage(this.backendApi.IdentityUsersKey, this.identityService.identityServiceUsers);
}
}

View file

@ -0,0 +1,66 @@
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { MatSelectModule } from "@angular/material/select";
import { MatFormFieldModule } from "@angular/material/form-field";
import { MatProgressBarModule } from "@angular/material/progress-bar";
import { HttpClientModule } from "@angular/common/http";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { TextFieldModule } from "@angular/cdk/text-field";
import { MatTooltipModule } from "@angular/material/tooltip";
import { AppRoutingModule } from "./app-routing.module";
import { AppComponent } from "./app.component";
import { BackendApiService } from "./backend-api.service";
import { GlobalVarsService } from "./global-vars.service";
import { IdentityService } from "./identity.service";
import { SpendLBCComponent } from "./spend-lbc/spend-lbc.component";
import { UiScrollModule } from "ngx-ui-scroll";
import { BsModalService } from "ngx-bootstrap/modal";
import { BsDropdownModule } from "ngx-bootstrap/dropdown";
import { PopoverModule } from "ngx-bootstrap/popover";
import { RatingModule } from "ngx-bootstrap/rating";
import { BsDatepickerModule } from "ngx-bootstrap/datepicker";
import { TimepickerModule } from "ngx-bootstrap/timepicker";
import { CollapseModule } from "ngx-bootstrap/collapse";
import { AnimateOnScrollModule } from "ng2-animate-on-scroll";
import { ToastrModule } from "ngx-toastr";
import { DragDropModule } from "@angular/cdk/drag-drop";
@NgModule({
declarations: [
AppComponent,
SpendLBCComponent,
],
imports: [
BrowserModule,
DragDropModule,
AppRoutingModule,
FormsModule,
MatSelectModule,
MatFormFieldModule,
MatProgressBarModule,
HttpClientModule,
ReactiveFormsModule,
BrowserAnimationsModule,
MatTooltipModule,
TextFieldModule,
UiScrollModule,
AnimateOnScrollModule.forRoot(),
ToastrModule.forRoot(),
BsDropdownModule.forRoot(),
PopoverModule.forRoot(),
RatingModule.forRoot(),
BsDatepickerModule.forRoot(),
TimepickerModule.forRoot(),
CollapseModule.forRoot(),
],
providers: [BackendApiService, GlobalVarsService, BsModalService, IdentityService],
bootstrap: [AppComponent],
})
export class AppModule {}

View file

@ -0,0 +1,192 @@
// FYI: any request that needs the HttpOnly cookie to be sent (e.g. b/c the server
// needs the seed phrase) needs the {withCredentials: true} option. It may also needed to
// get the browser to save the cookie in the response.
// https://github.com/github/fetch#sending-cookies
import { Injectable } from "@angular/core";
import { Observable, of, throwError } from "rxjs";
import { map, switchMap, catchError } from "rxjs/operators";
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { IdentityService } from "./identity.service";
export class BackendRoutes {
static RoutePathGetPsbt = "/transaction/psbt";
static RoutePathBroadcastTransaction = "/transaction/broadcast";
static RoutePathDecodeTransaction = "/transaction/decode";
}
export class User {
PublicKeyBase58Check: string;
EncryptedSeedHex: string;
// ...And other profile related stuff. email? isAdmin? etc etc.
}
@Injectable({
providedIn: "root",
})
export class BackendApiService {
constructor(private httpClient: HttpClient, private identityService: IdentityService) {}
// Store the identity users in localStorage
IdentityUsersKey = "identityUsersV2";
// Store last logged in user public key in localStorage
LastLoggedInUserKey = "lastLoggedInUserV2";
// Store the last identity service URL in localStorage
LastIdentityServiceKey = "lastIdentityServiceURLV2";
GetPsbt(endpoint: string, fromAddress: string, toAddress: string, desiredAmount: number): Observable<any> {
// TODO - Without JSON.stringify for some reason the body comes through empty.
// Not going to bother figuring this out now. We won't be using this http
// library in the end anyway.
return this.post(endpoint, BackendRoutes.RoutePathGetPsbt, JSON.stringify({
fromAddress, toAddress, desiredAmount
}));
}
BroadcastTransaction(endpoint: string, TransactionHex: string): Observable<any> {
return this.post(endpoint, BackendRoutes.RoutePathBroadcastTransaction, JSON.stringify({
transactionHex: TransactionHex,
}));
}
DecodeTransaction(endpoint: string, TransactionHex: string): Observable<any> {
return this.post(endpoint, BackendRoutes.RoutePathDecodeTransaction, JSON.stringify({
transactionHex: TransactionHex,
}));
}
SetStorage(key: string, value: any) {
localStorage.setItem(key, value || value === false ? JSON.stringify(value) : "");
}
RemoveStorage(key: string) {
localStorage.removeItem(key);
}
GetStorage(key: string) {
const data = localStorage.getItem(key);
if (data === "") {
return null;
}
return JSON.parse(data);
}
// Assemble a URL to hit the BE with.
_makeRequestURL(endpoint: string, routeName: string, adminPublicKey?: string): string {
let queryURL = location.protocol + "//" + endpoint + routeName;
// If the protocol is specified within the endpoint then use that.
if (endpoint.startsWith("http")) {
queryURL = endpoint + routeName;
}
if (adminPublicKey) {
queryURL += `?admin_public_key=${adminPublicKey}`;
}
return queryURL;
}
_handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error("An error occurred:", error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(`Backend returned code ${error.status}, ` + `body was: ${JSON.stringify(error.error)}`);
}
// return an observable with a user-facing error message
return throwError(error);
}
// Stores identity service users in identityService and localStorage
setIdentityServiceUsers(users: any, publicKeyAdded?: string) {
this.SetStorage(this.IdentityUsersKey, users);
this.identityService.identityServiceUsers = users;
this.identityService.identityServicePublicKeyAdded = publicKeyAdded;
}
signAndSubmitTransaction(endpoint: string, request: Observable<any>, PublicKeyBase58Check: string): Observable<any> {
// TODO - this could be useful to us. Either we go via iframe or via popup window. But for now disabling this function.
// stopping here for now
alert("not implemented. see the code")
return of(null)
return request
.pipe(
switchMap((res) =>
this.identityService
.sign({
transactionHex: res.TransactionHex,
...this.identityService.identityServiceParamsForKey(PublicKeyBase58Check),
})
.pipe(
switchMap((signed) => {
if (signed.approvalRequired) {
return this.identityService
.launch("/approve", {
tx: res.TransactionHex,
})
.pipe(
map((approved) => {
this.setIdentityServiceUsers(approved.users);
return { ...res, ...approved };
})
);
} else {
return of({ ...res, ...signed });
}
})
)
)
)
.pipe(
switchMap((res) => {
// TODO - changed the function name, but I still need to handle this right!
// stopping here for now
alert("not implemented. see the code")
return of(null)
return this.BroadcastTransaction(endpoint, res.signedTransactionHex).pipe(
map((broadcasted) => ({ ...res, ...broadcasted }))
)
})
)
.pipe(catchError(this._handleError));
}
get(endpoint: string, path: string) {
return this.httpClient.get<any>(this._makeRequestURL(endpoint, path)).pipe(catchError(this._handleError));
}
post(endpoint: string, path: string, body: any): Observable<any> {
if (endpoint.slice(-5) == ":8090") { // Suppress DeSo backend server calls. TODO - just remove those calls and remove this check.
return this.httpClient.post<any>(this._makeRequestURL(endpoint, path), body).pipe(catchError(this._handleError));
} else {
return of(null)
}
}
jwtPost(endpoint: string, path: string, publicKey: string, body: any): Observable<any> {
const request = this.identityService.jwt({
...this.identityService.identityServiceParamsForKey(publicKey),
});
return request.pipe(
switchMap((signed) => {
body = {
JWT: signed.jwt,
...body,
};
return this.post(endpoint, path, body).pipe(map((res) => ({ ...res, ...signed })));
})
);
}
}

View file

@ -0,0 +1,83 @@
import { Injectable } from "@angular/core";
import {
BackendApiService,
User,
} from "./backend-api.service";
import { Observable } from "rxjs";
import { environment } from "../environments/environment";
import { DomSanitizer } from "@angular/platform-browser";
import { IdentityService } from "./identity.service";
@Injectable({
providedIn: "root",
})
export class GlobalVarsService {
constructor(
private backendApi: BackendApiService,
private sanitizer: DomSanitizer,
private identityService: IdentityService,
) {}
// We track logged-in state
loggedInUser: User;
userList: User[] = [];
browserSupported = false;
// NEVER change loggedInUser property directly. Use this method instead.
// TODO delete this or repurpose it for LBRY
setLoggedInUser(user: User) {
const isSameUserAsBefore =
this.loggedInUser && user && this.loggedInUser.PublicKeyBase58Check === user.PublicKeyBase58Check;
this.loggedInUser = user;
if (!isSameUserAsBefore) {
// Store the user in localStorage
this.backendApi.SetStorage(this.backendApi.LastLoggedInUserKey, user?.PublicKeyBase58Check);
}
}
Init(loggedInUser: User, userList: User[]) {
this.userList = userList;
let identityServiceURL = this.backendApi.GetStorage(this.backendApi.LastIdentityServiceKey);
if (!identityServiceURL) {
identityServiceURL = environment.identityURL;
this.backendApi.SetStorage(this.backendApi.LastIdentityServiceKey, identityServiceURL);
}
this.identityService.identityServiceURL = identityServiceURL;
this.identityService.sanitizedIdentityServiceURL = this.sanitizer.bypassSecurityTrustResourceUrl(
`${identityServiceURL}/embed?v=2`
);
}
testSignActionLBRY() : Observable<string> {
const testActionHex = "deadbeefc001b0b1337"
return new Observable(subscriber => {
this.identityService.launch("/test-sign", { actionHex: testActionHex }).subscribe((res) => {
subscriber.next(res.signatureHex)
subscriber.complete()
});
});
}
testSignTransactionLBRY(psbtHex: string, nonWitnessUtxoHexes: string[], fromAddress: string) : Observable<string> {
return new Observable(subscriber => {
this.identityService.launch("/test-sign-transaction", { psbtHex, nonWitnessUtxoHexes: nonWitnessUtxoHexes.join(","), fromAddress }).subscribe((res) => {
subscriber.next(res.signedTransactionHex)
subscriber.complete()
});
});
}
testLoginLBRY() : Observable<string[]> {
return new Observable(subscriber => {
this.identityService.launch("/test-lbry-log-in", {}).subscribe((res) => {
// TODO - maybe we want public key instead of address? we should, as DeSo did, have a list of users with everything we need from them.
subscriber.next(res.addresses)
subscriber.complete()
});
});
}
}

View file

@ -0,0 +1,258 @@
import { Injectable } from "@angular/core";
import { Observable, Subject } from "rxjs";
import { v4 as uuid } from "uuid";
import { HttpParams } from "@angular/common/http";
@Injectable({
providedIn: "root",
})
export class IdentityService {
// Requests that were sent before the iframe initialized
private pendingRequests = [];
// All outbound request promises we still need to resolve
private outboundRequests = {};
// The currently active identity window
private identityWindow;
private identityWindowSubject;
// The URL of the identity service
identityServiceURL: string;
sanitizedIdentityServiceURL;
// User data
identityServiceUsers;
identityServicePublicKeyAdded: string;
private initialized = false;
private iframe = null;
// Wait for storageGranted broadcast
storageGranted = new Subject();
// Using testnet or mainnet
isTestnet = false;
constructor() {
window.addEventListener("message", (event) => this.handleMessage(event));
}
// Launch a new identity window
launch(
path?: string,
params?: {
publicKey?: string;
tx?: string;
actionHex?: string;
psbtHex?: string,
nonWitnessUtxoHexes?: string,
fromAddress?: string,
public_key?: string;
accessLevelRequest?: number;
}
): Observable<any> {
let url = this.identityServiceURL as string;
if (path) {
url += path;
}
let httpParams = new HttpParams();
if (this.isTestnet) {
httpParams = httpParams.append("testnet", "true");
}
if (params?.publicKey) {
httpParams = httpParams.append("publicKey", params.publicKey);
}
if (params?.tx) {
httpParams = httpParams.append("tx", params.tx);
}
if (params?.actionHex) {
httpParams = httpParams.append("actionHex", params.actionHex);
}
if (params?.psbtHex) {
// We don't want Base64 because "+" becomes a space.
httpParams = httpParams.append("psbtHex", params.psbtHex);
}
if (params?.nonWitnessUtxoHexes) {
httpParams = httpParams.append("nonWitnessUtxoHexes", params.nonWitnessUtxoHexes);
}
if (params?.fromAddress) {
httpParams = httpParams.append("fromAddress", params.fromAddress);
}
if (params?.public_key) {
httpParams = httpParams.append("public_key", params.public_key);
}
if (params?.accessLevelRequest) {
httpParams = httpParams.append("accessLevelRequest", params.accessLevelRequest.toString());
}
const paramsStr = httpParams.toString();
if (paramsStr) {
url += `?${paramsStr}`;
}
// center the window
const h = 1000;
const w = 800;
const y = window.outerHeight / 2 + window.screenY - h / 2;
const x = window.outerWidth / 2 + window.screenX - w / 2;
this.identityWindow = window.open(url, null, `toolbar=no, width=${w}, height=${h}, top=${y}, left=${x}`);
this.identityWindowSubject = new Subject();
return this.identityWindowSubject;
}
// Outgoing messages
sign(payload: {
accessLevel: number;
accessLevelHmac: string;
encryptedSeedHex: string;
transactionHex: string;
}): Observable<any> {
return this.send("sign", payload);
}
jwt(payload: { accessLevel: number; accessLevelHmac: string; encryptedSeedHex: string }): Observable<any> {
return this.send("jwt", payload);
}
info(): Observable<any> {
return this.send("info", {});
}
launchPhoneNumberVerification(public_key: string): Observable<{ phoneNumberSuccess: boolean }> {
return this.launch("/verify-phone-number", {
public_key,
});
}
// Helpers
identityServiceParamsForKey(publicKey: string) {
const { encryptedSeedHex, accessLevel, accessLevelHmac } = this.identityServiceUsers[publicKey];
return { encryptedSeedHex, accessLevel, accessLevelHmac };
}
// Incoming messages
private handleInitialize(event: MessageEvent) {
if (!this.initialized) {
this.initialized = true;
this.iframe = document.getElementById("identity");
for (const request of this.pendingRequests) {
this.postMessage(request);
}
this.pendingRequests = [];
}
// acknowledge, provides hostname data
this.respond(event.source as Window, event.data.id, {});
}
private handleStorageGranted() {
this.storageGranted.next(true);
this.storageGranted.complete();
}
private handleLogin(payload: any) {
this.identityWindow.close();
this.identityWindow = null;
this.identityWindowSubject.next(payload);
this.identityWindowSubject.complete();
this.identityWindowSubject = null;
}
private handleInfo(id: string) {
this.respond(this.identityWindow, id, {});
}
// Message handling
private handleMessage(event: MessageEvent) {
const { data } = event;
const { service, method } = data;
if (service !== "identity") {
return;
}
// Methods are present on incoming requests but not responses
if (method) {
this.handleRequest(event);
} else {
this.handleResponse(event);
}
}
private handleRequest(event: MessageEvent) {
const {
data: { id, method, payload },
} = event;
if (method === "initialize") {
this.handleInitialize(event);
} else if (method === "storageGranted") {
this.handleStorageGranted();
} else if (method === "login") {
this.handleLogin(payload);
} else if (method === "info") {
this.handleInfo(id);
} else {
console.error("Unhandled identity request");
console.error(event);
}
}
private handleResponse(event: MessageEvent) {
const {
data: { id, payload },
} = event;
const req = this.outboundRequests[id];
req.next(payload);
req.complete();
delete this.outboundRequests[id];
}
// Send a new message and expect a response
private send(method: string, payload: any) {
const req = {
id: uuid(),
method,
payload,
service: "identity",
};
const subject = new Subject();
this.postMessage(req);
this.outboundRequests[req.id] = subject;
return subject;
}
private postMessage(req: any) {
if (this.initialized) {
this.iframe.contentWindow.postMessage(req, "*");
} else {
this.pendingRequests.push(req);
}
}
// Respond to a received message
private respond(window: Window, id: string, payload: any): void {
window.postMessage({ id, service: "identity", payload }, "*");
}
}

View file

@ -0,0 +1,88 @@
<div class="container-lg border-left border-right landing__hero">
<div class="row">
<div class="col">
<div class="slide-up-2">
<a class="btn btn-primary landing__sign-up" (click)="testLoginLBRY()">
<div style="font-weight: bold; font-size: 20px;">
Log In
</div>
</a>
</div>
</div>
<div class="col">
<ng-container *ngIf="fromAddresses.length">
<b>From Addresses</b>: (TODO dropdown)
<ul>
<li *ngFor="let item of fromAddresses;">
<a target="_blank" href="https://explorer.lbry.com/find?q={{item}}">{{item}}</a>
</li>
</ul>
<br>
<br>
<b>To Address</b>: <input id="toAddress">
<br>
<br>
<b>Desired amount to spend</b>: <input id="desiredAmount">
<br>
<br>
<div class="slide-up-2">
<a class="btn btn-primary landing__sign-up" (click)="updatePsbt()">
<div style="font-weight: bold; font-size: 20px;">
Make PSBT
</div>
</a>
</div>
</ng-container>
<ng-container *ngIf="actualAmount">
<div style="overflow-wrap: break-word"><b>Actual amount to spend</b>: {{ actualAmount }}</div>
(including fees, based on input transaction(s) found. no change given)
<br>
<br>
<div style="overflow-wrap: break-word"><b>Fee</b>: {{ fee }}</div>
<br>
<div style="overflow-wrap: break-word"><b>psbtHex</b>: {{ psbtHex }}</div>
<br>
<div style="overflow-wrap: break-word">
<b>nonWitnessUtxoHexes</b>:
<ul>
<li *ngFor="let item of nonWitnessUtxoHexes;">
{{item}}
</li>
</ul>
</div>
<ng-container *ngIf="!lastErrorFull">
<div class="slide-up-2">
<a class="btn btn-primary landing__sign-up" (click)="testSignTransactionLBRY()">
<div style="font-weight: bold; font-size: 20px;">
Submit Payment
</div>
</a>
</div>
</ng-container>
</ng-container>
<ng-container *ngIf="signedTransactionHex">
<br>
<div style="overflow-wrap: break-word"><b>Signed Transaction Hex</b> (before submitting it for broadcast): {{ signedTransactionHex }}</div>
<br>
</ng-container>
<ng-container *ngIf="decodedTransaction">
<b>Decoded Signed Transaction</b> (before submitting it for broadcast):
<br>
<div style="white-space: pre; overflow-wrap: break-word">{{ decodedTransaction }}</div>
<br>
</ng-container>
<ng-container *ngIf="lastErrorFull">
<div>
<h1><font color="red">Error:</font></h1>
<h3><div style="white-space: pre; overflow-wrap: break-word">{{ lastError }}</div></h3>
<h2><font color="red">Details:</font></h2>
<div style="white-space: pre; overflow-wrap: break-word">{{ lastErrorFull }}</div>
</div>
</ng-container>
<ng-container *ngIf="success">
<h2><font color="green">I think it worked</font></h2>
<div style="white-space: pre; overflow-wrap: break-word">{{ success }}</div>
</ng-container>
</div>
</div>
</div>

View file

@ -0,0 +1,24 @@
import { ComponentFixture, TestBed } from "@angular/core/testing";
import { SpendLBCComponent } from "./spend-lbc.component";
describe("SpendLBCComponent", () => {
let component: SpendLBCComponent;
let fixture: ComponentFixture<SpendLBCComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [SpendLBCComponent],
}).compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SpendLBCComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it("should create", () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,160 @@
import { Component, OnInit } from "@angular/core";
import { AppRoutingModule } from "../app-routing.module";
import { GlobalVarsService } from "../global-vars.service";
import { environment } from "src/environments/environment";
import { BackendApiService } from "../backend-api.service";
@Component({
selector: "app-spend-lbc",
templateUrl: "./spend-lbc.component.html",
styleUrls: ["./spend-lbc.component.scss"],
})
export class SpendLBCComponent implements OnInit {
AppRoutingModule = AppRoutingModule;
environment = environment;
signatureHex = "";
signedTransactionHex = "";
psbtHex = "";
fromAddresses: string[] = [];
fromAddress: string = "";
nonWitnessUtxoHexes: string[] = [];
decodedTransaction = "";
lastError = "";
lastErrorFull = "";
actualAmount = 0;
fee = 0;
success = "";
constructor(
public globalVars: GlobalVarsService,
private backendApi: BackendApiService,
) {}
setError(err) {
if (err) {
this.success = ""
if (typeof err.error === "string") {
this.lastError = err.error
} else {
this.lastError = JSON.stringify(err.error, null, 2)
}
this.lastErrorFull = JSON.stringify(err, null, 2)
} else {
this.lastErrorFull = this.lastError = ""
}
}
ngOnInit() {
}
testSignActionLBRY() {
this.globalVars.testSignActionLBRY().subscribe({
next: (signatureHex) => {
this.signatureHex = signatureHex
},
error: err => { this.setError(err) }
})
}
updatePsbt() {
const toAddress = (<HTMLInputElement>document.getElementById("toAddress")).value;
const desiredAmount = Number((<HTMLInputElement>document.getElementById("desiredAmount")).value);
this.backendApi.GetPsbt("localhost:8090", this.fromAddress, toAddress, desiredAmount).subscribe({
next: res => {
this.psbtHex = res.psbtHex
this.nonWitnessUtxoHexes = res.nonWitnessUtxoHex
this.actualAmount = res.actualAmount
this.fee = res.actualAmount - desiredAmount
this.decodedTransaction = ""
this.signedTransactionHex = ""
this.setError(res.error && res)
},
// for some reason this leads to the function getting called with the same
// parameters but the values on the page don't get updated:
//
// error: this.setError
//
// so instead we do it more verbosely:
//
error: err => {
this.setError(err)
}
})
}
testLoginLBRY() {
this.globalVars.testLoginLBRY().subscribe({
next: (addresses) => {
this.fromAddresses = addresses
this.fromAddress = addresses[0]
},
error: err => { this.setError(err) }
})
}
testSignTransactionLBRY() {
this.globalVars.testSignTransactionLBRY(this.psbtHex, this.nonWitnessUtxoHexes, this.fromAddress).subscribe({
next: (signedTransactionHex) => {
this.signedTransactionHex = signedTransactionHex
this.backendApi.DecodeTransaction("localhost:8090", signedTransactionHex).subscribe({
next: res => {
this.decodedTransaction = res.decodedTransaction
console.log(res.decodedTransaction)
},
error: err => { this.setError(err) }
})
this.backendApi.BroadcastTransaction("localhost:8090", signedTransactionHex).subscribe({
next: res => {
this.setError(null)
this.success = res.txid
},
error: err => { this.setError(err) }
})
},
error: err => { this.setError(err) }
})
}
// TODO - store LBRY user identifier somewhere, maybe username, maybe collection of public keys in a wallet.
// And then query on the app side for the user's other info (profile?) as needed, from a hub or Odysee server or whatever.
// At least something, like avatar, so we have an example for developers. Do use the existing User struct for this.
// We won't have a list of users, but we will have a list of _accounts_ attached to the user.
// Actually maybe we won't! That's not good privacy.
}
// This demonstrates how to merge identity users with lbry users
// Actually maybe I should just go ahead and do this! At least a basic
// version. Then I can take it out of this "interesting example" file.
// actually... we don't need a list of users
// actually... maybe we need a list of accounts?
/*
launchLogoutFlow() {
const publicKey = this.globalVars.loggedInUser.PublicKeyBase58Check;
this.identityService.launch("/logout", { publicKey }).subscribe((res) => {
this.globalVars.userList = filter(this.globalVars.userList, (user) => {
return res?.users && user?.PublicKeyBase58Check in res?.users;
});
if (!res?.users) {
this.globalVars.userList = [];
}
let loggedInUser = get(Object.keys(res?.users), "[0]");
if (this.globalVars.userList.length === 0) {
loggedInUser = null;
this.globalVars.setLoggedInUser(null);
}
this.backendApi.setIdentityServiceUsers(res.users, loggedInUser);
this.globalVars.updateEverything().add(() => {
this.router.navigate(["/" + this.globalVars.RouteNames.BROWSE]);
});
});
}
*/

View file

View file

@ -0,0 +1,36 @@
{
"name": "deso",
"short_name": "deso",
"description": "The crypto social network",
"icons": [
{
"src": "/assets/bitclout/logo-192.png",
"type": "image/png",
"sizes": "192x192",
"purpose": "maskable"
},
{
"src": "/assets/bitclout/logo-512.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "maskable"
},
{
"src": "/assets/bitclout/logo-192.png",
"type": "image/png",
"sizes": "192x192",
"purpose": "any"
},
{
"src": "/assets/bitclout/logo-512.png",
"type": "image/png",
"sizes": "512x512",
"purpose": "any"
}
],
"start_url": "/",
"scope": "/",
"display": "standalone",
"theme_color": "#182026",
"background_color": "#FFF"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

@ -0,0 +1,7 @@
<svg width="138" height="28" viewBox="0 0 138 28" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M29.7001 21.7632H35.7321C40.1781 21.7632 42.9601 20.5932 42.9601 16.9012C42.9601 13.6252 40.7501 12.4812 37.9421 12.4292V11.8052C39.8401 11.6752 41.6081 10.5832 41.6081 7.93118C41.6081 4.31718 39.0341 3.43318 34.5621 3.43318H29.7001V21.7632ZM31.8321 11.3112V5.25318H34.6401C37.6301 5.25318 39.4761 5.43518 39.4761 8.26918C39.4761 10.8692 37.6301 11.3112 34.6401 11.3112H31.8321ZM31.8321 19.9432V13.1312H35.8101C38.9301 13.1312 40.8281 13.8592 40.8281 16.5372C40.8281 19.4232 38.9301 19.9432 35.8101 19.9432H31.8321ZM49.2637 6.78718C50.3037 6.78718 51.1357 6.00718 51.1357 4.96718C51.1357 3.97918 50.3037 3.17318 49.2637 3.17318C48.1977 3.17318 47.3917 3.97918 47.3917 4.96718C47.3917 6.00718 48.1977 6.78718 49.2637 6.78718ZM44.9477 21.7632H54.2297V19.9432H50.5897V10.1412C50.5897 9.15318 50.1217 8.47718 48.8997 8.58118L45.9097 8.84118V10.6612L48.5877 10.4272V19.9432H44.9477V21.7632ZM59.29 20.2292V10.6612H63.32V8.84118H59.29V4.86318L57.184 5.51318V8.84118H54.324V10.6612H57.184V20.2552C57.184 21.4512 57.73 22.1012 58.952 22.0232L63.84 21.7632V19.9432L59.29 20.2292ZM66.612 12.5852C66.612 17.9412 69.81 22.0232 75.192 22.0232C79.872 22.0232 82.94 19.2152 83.486 14.6652H81.354C80.938 18.1752 78.78 20.2032 75.192 20.2032C70.928 20.2032 68.744 17.0312 68.744 12.5852C68.744 8.16518 70.928 4.99318 75.192 4.99318C78.78 4.99318 80.938 6.99518 81.354 10.5052H83.486C82.94 5.98118 79.872 3.17318 75.192 3.17318C69.81 3.17318 66.612 7.25518 66.612 12.5852ZM84.7033 21.7632H94.0633V19.9432H90.4493V4.18718C90.4493 2.96518 89.8773 2.28918 88.6813 2.39318L85.6653 2.65318V4.47318L88.3433 4.23918V19.9432H84.7033V21.7632ZM95.5258 15.2892C95.5258 19.0592 98.2298 22.0232 102.364 22.0232C106.472 22.0232 109.15 19.0592 109.15 15.2892C109.15 11.5452 106.472 8.58118 102.364 8.58118C98.2298 8.58118 95.5258 11.5452 95.5258 15.2892ZM97.6578 15.2892C97.6578 12.6112 99.2958 10.4012 102.364 10.4012C105.406 10.4012 107.044 12.6112 107.044 15.2892C107.044 17.9932 105.406 20.2032 102.364 20.2032C99.2958 20.2032 97.6578 17.9932 97.6578 15.2892ZM117.266 20.2032C115.03 20.2032 113.99 19.1632 113.99 16.4592V8.84118H111.858V16.7452C111.858 20.3332 113.756 22.0232 116.694 22.0232C119.502 22.0232 121.14 20.3852 121.66 18.0452H122.258L121.92 19.5272V21.7632H124.026V8.84118H121.92V14.5872C121.92 18.0452 119.996 20.2032 117.266 20.2032ZM131.247 20.2292V10.6612H135.277V8.84118H131.247V4.86318L129.141 5.51318V8.84118H126.281V10.6612H129.141V20.2552C129.141 21.4512 129.687 22.1012 130.909 22.0232L135.797 21.7632V19.9432L131.247 20.2292Z" fill="#222222"/>
<path d="M9.66243 25.3511L17.6755 15.2309C17.8052 15.067 17.6885 14.8257 17.4795 14.8257H0.907031C0.694218 14.8257 0.57872 15.0746 0.716149 15.2371L9.27554 25.3574C9.37753 25.478 9.56439 25.475 9.66243 25.3511Z" fill="white" stroke="black"/>
<path d="M17.5745 14.3587L9.44746 10.4872C9.30597 10.4197 9.14105 10.4226 9.00196 10.4948L0.999407 14.6513C0.650668 14.8324 0.637574 15.3265 0.976231 15.5259L8.96405 20.2278C9.1233 20.3216 9.32127 20.3198 9.47885 20.2233L17.6206 15.2365C17.9589 15.0293 17.9327 14.5294 17.5745 14.3587Z" fill="white" stroke="black"/>
<path d="M9.66243 15.971L17.6755 5.85075C17.8052 5.68686 17.6885 5.44556 17.4795 5.44556H0.907031C0.694218 5.44556 0.57872 5.69451 0.716149 5.857L9.27554 15.9773C9.37753 16.0979 9.56439 16.0948 9.66243 15.971Z" fill="white" stroke="black"/>
<path d="M17.5745 4.97862L9.44746 1.10703C9.30597 1.03962 9.14105 1.04246 9.00196 1.1147L0.999407 5.27113C0.650668 5.45226 0.637574 5.9464 0.976231 6.14574L8.96405 10.8477C9.1233 10.9414 9.32127 10.9397 9.47885 10.8432L17.6206 5.85639C17.9589 5.64915 17.9327 5.14926 17.5745 4.97862Z" fill="white" stroke="black"/>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="704pt" height="801pt" viewBox="0 0 704 801" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g id="#000000ff">
<path fill="#000000" opacity="1.00" d=" M 273.03 42.04 C 299.57 28.75 325.97 15.16 352.57 2.00 C 442.37 47.92 532.24 93.71 622.15 139.42 C 616.20 148.00 609.48 156.04 603.23 164.41 C 554.73 227.60 506.20 290.76 457.70 353.95 C 512.62 381.98 567.58 409.91 622.49 437.96 C 532.95 554.49 443.40 671.01 353.83 787.52 C 262.59 671.00 171.37 554.47 80.15 437.94 C 135.98 409.75 191.82 381.56 247.65 353.34 C 191.89 282.04 136.17 210.71 80.38 139.43 C 144.53 106.85 208.84 74.55 273.03 42.04 M 144.87 138.36 C 213.96 175.07 283.07 211.77 352.16 248.48 C 421.07 211.91 489.97 175.33 558.87 138.77 C 489.97 103.74 421.08 68.68 352.18 33.66 C 283.06 68.53 213.96 103.43 144.87 138.36 M 136.71 165.58 C 209.17 258.00 281.50 350.52 353.84 443.03 C 424.45 350.88 495.27 258.89 565.97 166.80 C 494.73 204.53 423.57 242.40 352.34 280.12 C 280.47 241.93 208.62 203.69 136.71 165.58 M 144.84 436.71 C 213.93 473.40 283.15 509.84 352.19 546.63 C 421.24 510.23 490.11 473.47 559.09 436.92 C 519.48 416.83 479.88 396.72 440.30 376.58 C 411.47 414.11 382.66 451.64 353.84 489.15 C 324.30 451.45 294.80 413.71 265.26 376.00 C 225.11 396.21 185.00 416.50 144.84 436.71 M 136.50 464.12 C 208.83 556.64 281.25 649.10 353.61 741.60 C 424.45 649.48 495.20 557.28 566.02 465.13 C 494.70 502.96 423.44 540.90 352.12 578.71 C 280.26 540.48 208.38 502.30 136.50 464.12 Z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -0,0 +1,30 @@
<svg width="82" height="30" viewBox="0 0 82 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M31.6461 21V7.49219H35.4591C36.6342 7.49219 37.6733 7.75195 38.5763 8.27148C39.4793 8.79102 40.1751 9.53011 40.6637 10.4888C41.1585 11.4474 41.409 12.5483 41.4152 13.7915V14.6543C41.4152 15.9284 41.1678 17.0448 40.673 18.0034C40.1844 18.9621 39.4824 19.6981 38.567 20.2114C37.6578 20.7248 36.5971 20.9876 35.3849 21H31.6461ZM33.4274 8.95801V19.5435H35.3014C36.6744 19.5435 37.7413 19.1167 38.5021 18.2632C39.269 17.4097 39.6525 16.1943 39.6525 14.6172V13.8286C39.6525 12.2948 39.2907 11.1042 38.567 10.2568C37.8496 9.40332 36.8291 8.97038 35.5055 8.95801H33.4274ZM48.0114 21.1855C46.6507 21.1855 45.5436 20.7402 44.6901 19.8496C43.8366 18.9528 43.4098 17.756 43.4098 16.2593V15.9438C43.4098 14.9481 43.5984 14.0605 43.9757 13.2812C44.3592 12.4958 44.8911 11.8835 45.5714 11.4443C46.2579 10.999 47.0001 10.7764 47.798 10.7764C49.103 10.7764 50.1173 11.2062 50.841 12.0659C51.5646 12.9256 51.9264 14.1564 51.9264 15.7583V16.4727H45.1261C45.1508 17.4622 45.4384 18.2632 45.9889 18.8755C46.5455 19.4816 47.2506 19.7847 48.1041 19.7847C48.7103 19.7847 49.2236 19.661 49.6442 19.4136C50.0647 19.1662 50.4327 18.8384 50.7482 18.4302L51.7965 19.2466C50.9554 20.5392 49.6937 21.1855 48.0114 21.1855ZM47.798 12.1865C47.1053 12.1865 46.5239 12.4401 46.0538 12.9473C45.5838 13.4482 45.2931 14.1533 45.1818 15.0625H50.2101V14.9326C50.1606 14.0605 49.9256 13.3864 49.505 12.9102C49.0844 12.4277 48.5154 12.1865 47.798 12.1865ZM58.1701 14.979C56.6424 14.5399 55.5291 14.0018 54.8302 13.3647C54.1375 12.7215 53.7911 11.9299 53.7911 10.9897C53.7911 9.92594 54.2148 9.04769 55.0621 8.35498C55.9157 7.65609 57.0228 7.30664 58.3834 7.30664C59.3112 7.30664 60.1368 7.486 60.8605 7.84473C61.5903 8.20345 62.1531 8.69824 62.549 9.3291C62.951 9.95996 63.152 10.6496 63.152 11.3979H61.3615C61.3615 10.5815 61.1017 9.94141 60.5822 9.47754C60.0626 9.00749 59.3297 8.77246 58.3834 8.77246C57.5052 8.77246 56.8187 8.96729 56.3239 9.35693C55.8353 9.7404 55.591 10.2754 55.591 10.9619C55.591 11.5124 55.8229 11.9793 56.2868 12.3628C56.7568 12.7401 57.5516 13.0864 58.671 13.4019C59.7967 13.7173 60.6749 14.0667 61.3058 14.4502C61.9428 14.8275 62.4129 15.2697 62.716 15.7769C63.0252 16.284 63.1798 16.8809 63.1798 17.5674C63.1798 18.6621 62.7531 19.5404 61.8995 20.2021C61.046 20.8577 59.9049 21.1855 58.4762 21.1855C57.5485 21.1855 56.6826 21.0093 55.8785 20.6567C55.0745 20.298 54.4529 19.8094 54.0138 19.1909C53.5809 18.5724 53.3644 17.8704 53.3644 17.085H55.1549C55.1549 17.9014 55.4549 18.5477 56.0548 19.0239C56.6609 19.494 57.4681 19.729 58.4762 19.729C59.4163 19.729 60.1368 19.5373 60.6378 19.1538C61.1388 18.7703 61.3893 18.2477 61.3893 17.5859C61.3893 16.9242 61.1574 16.4139 60.6935 16.0552C60.2296 15.6903 59.3885 15.3315 58.1701 14.979ZM64.7477 15.8882C64.7477 14.9048 64.9394 14.0203 65.3229 13.2349C65.7125 12.4494 66.2506 11.8433 66.9371 11.4165C67.6298 10.9897 68.4184 10.7764 69.3029 10.7764C70.6697 10.7764 71.7737 11.2495 72.6149 12.1958C73.4622 13.1421 73.8859 14.4007 73.8859 15.9717V16.0923C73.8859 17.0695 73.6972 17.9478 73.32 18.7271C72.9489 19.5002 72.4139 20.1032 71.715 20.5361C71.0223 20.9691 70.2244 21.1855 69.3214 21.1855C67.9607 21.1855 66.8567 20.7124 66.0094 19.7661C65.1683 18.8198 64.7477 17.5674 64.7477 16.0088V15.8882ZM66.4733 16.0923C66.4733 17.2056 66.7299 18.0993 67.2433 18.7734C67.7628 19.4476 68.4555 19.7847 69.3214 19.7847C70.1935 19.7847 70.8862 19.4445 71.3995 18.7642C71.9129 18.0776 72.1696 17.119 72.1696 15.8882C72.1696 14.7873 71.9067 13.8966 71.381 13.2163C70.8615 12.5298 70.1687 12.1865 69.3029 12.1865C68.4555 12.1865 67.7721 12.5236 67.2526 13.1978C66.733 13.8719 66.4733 14.8368 66.4733 16.0923Z" fill="black"/>
<g clip-path="url(#clip1)">
<path d="M3.15948 2.08691V8.31256L19.5455 17.4154L3.15948 26.9933H16.6605C20.9744 26.9933 24.4685 23.9284 24.4685 20.1471V14.5421L3.15948 2.08691Z" fill="url(#paint0_linear)"/>
<path d="M3.15948 2.08691L24.4685 14.542V8.93321C24.4685 5.15185 20.9706 2.08691 16.6605 2.08691H3.15948Z" fill="url(#paint1_linear)"/>
<path d="M14.3694 14.5422L3.15942 20.7679V26.9935L19.5453 17.4156L14.3694 14.5422Z" fill="url(#paint2_linear)"/>
</g>
</g>
<defs>
<linearGradient id="paint0_linear" x1="8.39778" y1="7.68815" x2="15.8095" y2="25.5881" gradientUnits="userSpaceOnUse">
<stop stop-color="#0057FF"/>
<stop offset="1" stop-color="#00A3FF"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="11.8747" y1="7.81472" x2="25.6627" y2="4.17261" gradientUnits="userSpaceOnUse">
<stop stop-color="#0283FF"/>
<stop offset="1" stop-color="#01C2FF"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="7.13594" y1="24.6867" x2="26.4463" y2="-0.936721" gradientUnits="userSpaceOnUse">
<stop stop-color="#0157FF"/>
<stop offset="1" stop-color="#00FFFF"/>
</linearGradient>
<clipPath id="clip0">
<rect width="82" height="30" fill="white"/>
</clipPath>
<clipPath id="clip1">
<rect width="21.5909" height="25" fill="white" transform="translate(3 2)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View file

@ -0,0 +1,19 @@
<svg width="939" height="1068" viewBox="0 0 939 1068" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M102.51 105.004V320.162L668.672 634.758L102.51 965.77H568.993C718.042 965.77 838.771 859.846 838.771 729.163V535.454L102.51 105.004Z" fill="url(#paint0_linear)"/>
<path d="M102.51 105.004L838.771 535.453V341.612C838.771 210.928 717.913 105.004 568.993 105.004H102.51Z" fill="url(#paint1_linear)"/>
<path d="M489.831 535.458L102.508 750.617V965.776L668.666 634.762L489.831 535.458Z" fill="url(#paint2_linear)"/>
<defs>
<linearGradient id="paint0_linear" x1="283.501" y1="298.582" x2="539.696" y2="917.162" gradientUnits="userSpaceOnUse">
<stop stop-color="#0057FF"/>
<stop offset="1" stop-color="#00A3FF"/>
</linearGradient>
<linearGradient id="paint1_linear" x1="403.635" y1="302.957" x2="880.046" y2="177.143" gradientUnits="userSpaceOnUse">
<stop stop-color="#0283FF"/>
<stop offset="1" stop-color="#01C2FF"/>
</linearGradient>
<linearGradient id="paint2_linear" x1="239.903" y1="886.052" x2="907.313" y2="0.663357" gradientUnits="userSpaceOnUse">
<stop stop-color="#0157FF"/>
<stop offset="1" stop-color="#00FFFF"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View file

@ -0,0 +1,13 @@
<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g>
<path d="M123.44,80.64c-0.16-5.36-1.3-10.67-3.36-15.61c-1-2.41-2.22-4.72-3.63-6.91 c-1.11-1.72-2.21-2.93-2.6-4.83c-0.05-0.25-0.09-0.51-0.12-0.79c-0.12-1.29,0.11-2.16,0.33-3.4c1.09-6.19-0.83-10.09-5.76-13.8 c-0.04-0.03-0.09-0.06-0.14-0.09c1.46-2.36,2.55-4.95,3.11-7.68c1.91-9.36-2.95-19.56-11.67-23.63c-2.95-1.37-6.04-2.11-9.19-2.33 C83.58,1.09,76.56,3.03,70.48,6.1c-8.4,4.24-14.81,11.66-23.51,15.31c-2.05,0.86-3.9,1.24-6.09,1.44 c-1.45,0.14-3.12-0.16-4.57-0.29c-2.14-0.18-5.33-2.08-6.44,0.87c-1.5,4,6.23,4.51,8.52,4.76c8.69,0.94,19.67-5.55,26.17-10.89 c9.23-7.58,24.94-15.72,35.81-6.27c6.24,5.43,6.98,14.72,2.39,21.34c-0.83-0.29-1.68-0.56-2.54-0.76c-2.71-0.62-5.16-0.49-7.52,1 c-1.94,1.23-3.65,2.76-5.43,4.19c-1.6,1.28-2.59,1.06-4.57,0.85c-1.45-0.15-2.9-0.24-4.36-0.24c-24.92,0-45.11,19.94-45.11,44.54 c0,24.6,20.2,44.54,45.11,44.54c24.91,0,45.11-19.94,45.11-44.54C123.45,81.52,123.45,81.08,123.44,80.64z" style="fill:#2F2F2F;"/>
<path d="M88.19,51.76c-2.74,0.74-5.68,0.7-8.47,1.37c-5.43,1.31-10.56,3.8-14.94,7.26 c-9.02,7.13-14.53,18.32-14.48,29.82c0,0.54,0.01,1.08,0.04,1.62c0.09,1.87,0.18,4.67-1.42,6.03c-4.63,3.94-8.51-8.6-8.91-11.02 c-0.83-5.09-0.26-10.51,1.18-15.44c1.53-5.26,4.22-10.15,7.81-14.28c7.33-8.44,18.17-13.31,29.34-13.31c2.92,0,6.04,0.22,8.87,1.01 c2.13,0.6,4.76,1.33,5.63,3.65C93.98,51.51,90.1,51.25,88.19,51.76z" style="fill:#FFFFFF;"/>
<circle cx="22.77" cy="22.33" r="3.74" style="fill:#ED6C30;"/>
<path d="M19.97,29.47c-1.58,1.69-3.42,5.87-3.21,8.3c0.05,0.63,0.22,1.24,0.51,1.81 c0.7,1.36,2.77,2.24,4.1,1.37c1.04-0.67,1.62-1.79,1.9-2.98C23.69,36.21,23.76,25.43,19.97,29.47z" style="fill:#ED6C30;"/>
<path d="M34.96,36.25c0.28-1.13-0.04-2.27-0.59-3.26c-0.83-1.49-7.65-8.94-7.69-3.75 c0,2.16,1.39,6.22,3.08,7.75c0.44,0.4,0.94,0.71,1.5,0.92C32.6,38.4,34.59,37.68,34.96,36.25z" style="fill:#ED6C30;"/>
<path d="M15.45,24.95c-2.14,0.11-6.06,1.72-7.48,3.46c-0.37,0.46-0.66,0.97-0.83,1.54 c-0.41,1.35,0.41,3.28,1.85,3.55c1.13,0.22,2.23-0.16,3.18-0.76C13.6,31.84,20.58,24.69,15.45,24.95z" style="fill:#ED6C30;"/>
<path d="M35.2,12.77c0.72-0.97,1.22-2.12,1.08-3.36c-0.18-1.57-2.19-2.61-3.67-2.27 c-0.63,0.14-1.21,0.41-1.72,0.76c-2,1.39-4.04,5.48-4.33,7.77C25.86,21.17,34.1,14.23,35.2,12.77z" style="fill:#ED6C30;"/>
<path d="M15.3,20.97c2.84-0.78,1.06-2.76-0.43-3.89c-1.8-1.36-4.23-2.89-6.52-3.18 c-1.44-0.18-3.01,0.64-3.58,1.97c-0.7,1.62,0.33,3.19,1.69,4.07C8.51,21.26,13.07,21.58,15.3,20.97z" style="fill:#ED6C30;"/>
<path d="M21.95,7.11c-0.37-1.08-1-2.08-2.03-2.62c-1.31-0.69-3.18,0.32-3.71,1.64 c-0.22,0.56-0.32,1.14-0.32,1.74c0.02,2.28,2.1,6.03,3.72,7.48C23.5,18.79,22.5,8.73,21.95,7.11z" style="fill:#ED6C30;"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
y="0px" viewBox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="131.7595" y1="126.9437" x2="33.399" y2="21.8985" gradientTransform="matrix(0.9948 0.035 0.0441 -0.9944 -18.6329 133.5839)">
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0"/>
<stop offset="0.1566" style="stop-color:#D3F0F9;stop-opacity:0.1566"/>
<stop offset="0.3654" style="stop-color:#9FDFF3;stop-opacity:0.3654"/>
<stop offset="0.5612" style="stop-color:#76D2EE;stop-opacity:0.5612"/>
<stop offset="0.7383" style="stop-color:#58C8EA;stop-opacity:0.7383"/>
<stop offset="0.8904" style="stop-color:#46C2E8;stop-opacity:0.8904"/>
<stop offset="1" style="stop-color:#40C0E7"/>
</linearGradient>
<path style="fill:url(#SVGID_1_);" d="M28.8,123.12c-7.67,5.38-17.35,6.15-23.57-0.86s-4.82-16.55,0.64-24.32
C16.49,82.85,83.8,1.31,83.8,1.31s21.18-3.99,34,11.33s9.01,35.08,9.01,35.08S44.33,112.24,28.8,123.12z"/>
<path style="fill:#ED6C30;" d="M80.24,53.33"/>
<path style="fill:#ED6C30;" d="M85.09,48.85"/>
<path style="fill:#ED6C30;" d="M74.16,43.72"/>
<path style="fill:#ED6C30;" d="M72.47,43.11"/>
<path style="fill:#ED6C30;" d="M72.06,41.14"/>
<path style="fill:#ED6C30;" d="M72.67,40.58"/>
<linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="128.0569" y1="127.8521" x2="29.5315" y2="23.9678" gradientTransform="matrix(0.9989 0.0469 0.0469 -0.9989 -18.6484 137.6311)">
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0"/>
<stop offset="1" style="stop-color:#B388FF"/>
</linearGradient>
<path style="opacity:0.5;fill:url(#SVGID_2_);enable-background:new ;" d="M3.7,106.8c6.52-9.74,33.69-41.77,49.65-55.79
C69.31,37,74.04,32.55,88.93,21.64c3.5-2.56,14.38-2.51,18.6,2.92c4.73,6.08,3.24,14.42,1.28,17.76
c-1.41,2.4-20.34,24.63-32.45,35.35s-50.52,45.07-56.8,48.04c-6.28,2.96-11.61-0.81-14.53-3.68C2.11,119.15,0.92,110.97,3.7,106.8z"
/>
<linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="96.5229" y1="90.3611" x2="32.6698" y2="27.6347" gradientTransform="matrix(0.9992 0.0397 0.0397 -0.9992 -15.8837 136.3304)">
<stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0"/>
<stop offset="1" style="stop-color:#E0F7FA"/>
</linearGradient>
<path style="fill:url(#SVGID_3_);" d="M6.93,107.4c0,0,29.01-25.87,46.35-39.39c37.44-29.21,20.74-5.81-33.05,52.38
C20.23,120.38,9.49,124.16,6.93,107.4z"/>
<path style="fill:#E0F7FA;" d="M19.54,108.15c3.41,3.84,3.18,9.83-0.51,13.38c-3.69,3.55-9.45,3.31-12.86-0.53
s-3.18-9.83,0.51-13.38C10.38,104.07,16.13,104.31,19.54,108.15z"/>
<g>
<circle style="fill:#FFFFFF;" cx="21" cy="116" r="1"/>
<circle style="fill:#FFFFFF;" cx="19" cy="102" r="1"/>
<circle style="fill:#FFFFFF;" cx="19" cy="92.25" r="1"/>
<circle style="fill:#FFFFFF;" cx="11" cy="116" r="1.75"/>
<circle style="fill:#FFFFFF;" cx="24" cy="107" r="1.75"/>
<circle style="fill:#FFFFFF;" cx="30" cy="97.75" r="1.75"/>
<circle style="fill:#FFFFFF;" cx="12.75" cy="108.75" r="1.75"/>
<circle style="fill:#FFFFFF;" cx="40.2" cy="103" r="1"/>
<circle style="fill:#FFFFFF;" cx="52.5" cy="90.5" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="43.25" cy="91" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="71.25" cy="63" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="52.25" cy="75" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="41" cy="75" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="107" cy="36.25" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="91" cy="35.75" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="90.75" cy="48" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="63.25" cy="57" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="67" cy="84" r="1"/>
<circle style="fill:#FFFFFF;" cx="67" cy="72" r="1"/>
<circle style="fill:#FFFFFF;" cx="46" cy="64" r="1"/>
<circle style="fill:#FFFFFF;" cx="38" cy="67" r="1"/>
<circle style="fill:#FFFFFF;" cx="72" cy="42" r="1"/>
<circle style="fill:#FFFFFF;" cx="56.5" cy="58.5" r="1.25"/>
<circle style="fill:#FFFFFF;" cx="53" cy="56" r="1"/>
<circle style="fill:#FFFFFF;" cx="31.75" cy="111.5" r="1"/>
<circle style="fill:#FFFFFF;" cx="33" cy="78" r="1"/>
<circle style="fill:#FFFFFF;" cx="30" cy="87.09" r="1"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -0,0 +1,61 @@
<svg width="128" height="128" style="enable-background:new 0 0 128 128;" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="图层_1">
<path d="M1827.42,49.04c-0.01-2.6-0.17-5.16-0.47-7.62c-2-16.35-11.24-30.55-24.12-37.07 c-6.06-3.06-12.39-4.29-18.93-3.66c-12.49,1.25-25.33,8.45-32.73,20.82c-17.74,29.67-6.38,65.56-3.38,71.66 c15.34,31.17,40.12,33.83,52.62,32.82c13.58-1.1,29.43-6.61,31.69-12.81c0.53-1.47,0.46-3.06-0.2-4.48 c-1.3-2.75-3.95-2.49-4.82-2.41l-0.99,0.11l-0.26,0.01c-3.78-0.05-5.44-1.02-6.59-3.81c-1.75-4.27-0.31-10.54,1.15-15.52 C1823.38,76.85,1827.49,62.84,1827.42,49.04z" style="fill:#EEEEEE;"/>
<path d="M1589.43,43.38c2.03-0.26,4.2-0.43,6.25-0.1c2.09,0.35,4.09,1.47,6.27,1.28 c1.42-0.12,3-1.04,3.88-2.14c1.88-2.32,2.21-5.45,1.37-8.24c-0.61-2-1.82-3.82-3.52-5.06c-4.16-3.05-10.51-1.68-14.22,1.67 c-2.8,2.52-6.88,7.72-5.29,11.87C1584.86,44.45,1588.14,43.53,1589.43,43.38z" style="fill:#2F2F2F;"/>
<path d="M1558.14,41.43c1.63,0.58,3.39,0.03,4.96,0.14c1.46,0.1,2.8,0.62,3.99,1.16 c0.71,0.32,2.31,1.45,3.19,0.3c2.13-2.73,1.6-7.74,0.8-10.77c-1.21-4.59-5.47-8.92-10.14-7.24c-1.96,0.71-3.67,2.36-4.81,4.48 c-1.53,2.85-1.94,6.31-0.75,9.13C1555.9,39.86,1557,41.02,1558.14,41.43z" style="fill:#2F2F2F;"/>
<path d="M1590.7,50.64c-4.66,0.07-8.6,3.68-12.97,3.98c-4.29,0.31-6.55-0.8-9.68-3.48 c-4.84-4.14-10.49,0-9.32,6.26c0.51,2.74,1.57,5.22,3.04,7.37c4.18,6.16,11.86,9.71,19.55,7.56c4.72-1.32,9.75-4.86,13.41-8.65 C1599.44,58.81,1598.66,50.53,1590.7,50.64z" style="fill:#2F2F2F;"/>
<path d="M1825.74,71.94c7.12,0.71,16.13-2.71,20.21-7.53c3.31-3.92,5.83-9.63,5.78-15.4 c-0.02-2.31-0.44-4.64-1.41-6.86c-1.11-2.53-2.77-4.3-4.83-5.09c-1.08-0.41-2.7-0.73-4.7-0.15c-0.38,0.12-0.79,0.26-1.18,0.45 c-2.93,1.3-4.42,3.46-5.75,5.38c-1.03,1.5-2.31,3.26-3.79,4.35c-0.67,0.5-1.16,0.8-1.97,1.04c-0.81,0.23-1.61,0.32-2.43,0.1 c-0.64-0.15-1.23-0.61-1.88-0.68c-1.68-0.2-2.19,1.4-1.4,2.65C1823.09,51.31,1825.53,71.92,1825.74,71.94z" style="fill:#EEEEEE;"/>
<path d="M1749.72,71.94c-7.12,0.71-16.13-2.71-20.21-7.53c-3.31-3.92-5.83-9.63-5.78-15.4 c0.02-2.31,0.44-4.64,1.41-6.86c1.11-2.53,2.77-4.3,4.83-5.09c1.08-0.41,2.7-0.73,4.7-0.15c0.38,0.12,0.79,0.26,1.18,0.45 c2.93,1.3,4.42,3.46,5.75,5.38c1.03,1.5,2.31,3.26,3.79,4.35c0.67,0.5,1.16,0.8,1.97,1.04c0.81,0.23,1.61,0.32,2.43,0.1 c0.64-0.15,1.23-0.61,1.88-0.68c1.68-0.2,2.19,1.4,1.4,2.65C1752.37,51.31,1749.93,71.92,1749.72,71.94z" style="fill:#EEEEEE;"/>
<g>
<path d="M1677.44,43.69c2.18-0.37,4.52-0.65,6.75-0.42c2.28,0.24,4.5,1.26,6.85,0.96 c1.53-0.19,3.18-1.19,4.08-2.33c1.9-2.41,2.09-5.55,1.03-8.3c-0.77-1.97-2.18-3.73-4.09-4.87c-4.67-2.83-11.35-1.04-15.27,2.4 c-4.02,3.53-6.96,9.51-5.06,12.13C1672.87,44.84,1676.06,43.91,1677.44,43.69z" style="fill:#2F2F2F;"/>
<path d="M1650.22,43.69c-2.18-0.37-4.52-0.65-6.75-0.42c-2.28,0.24-4.5,1.26-6.85,0.96 c-1.53-0.19-3.18-1.19-4.08-2.33c-1.9-2.41-2.09-5.55-1.03-8.3c0.77-1.97,2.18-3.73,4.09-4.87c4.67-2.83,11.35-1.04,15.27,2.4 c4.02,3.53,6.96,9.51,5.06,12.13C1654.79,44.84,1651.6,43.91,1650.22,43.69z" style="fill:#2F2F2F;"/>
<g>
<path d="M1678.01,50.64c-5.73,0.51-8.92,4.97-15.16,4.97v17.31c7.7,0,15.63-4.38,19.52-9.24 C1686.77,58.19,1686.57,49.88,1678.01,50.64z" style="fill:#2F2F2F;"/>
<path d="M1647.69,50.64c5.73,0.51,8.92,4.97,15.16,4.97v17.31c-7.7,0-15.63-4.38-19.52-9.24 C1638.93,58.19,1639.13,49.88,1647.69,50.64z" style="fill:#2F2F2F;"/>
</g>
</g>
<g>
<path d="M1798.56,45.01c1.74-0.29,3.59-0.51,5.37-0.34c1.81,0.19,3.58,1,5.45,0.76 c1.22-0.15,2.53-0.95,3.24-1.86c1.51-1.92,1.66-4.42,0.82-6.6c-0.62-1.57-1.74-2.96-3.25-3.87c-3.71-2.25-9.03-0.83-12.15,1.91 c-3.2,2.8-5.53,7.56-4.02,9.65C1794.92,45.92,1797.46,45.18,1798.56,45.01z" style="fill:#2F2F2F;"/>
<path d="M1776.9,45.01c-1.74-0.29-3.59-0.51-5.37-0.34c-1.81,0.19-3.58,1-5.45,0.76 c-1.22-0.15-2.53-0.95-3.24-1.86c-1.51-1.92-1.66-4.42-0.82-6.6c0.62-1.57,1.74-2.96,3.25-3.87c3.71-2.25,9.03-0.83,12.15,1.91 c3.2,2.8,5.53,7.56,4.02,9.65C1780.54,45.92,1778,45.18,1776.9,45.01z" style="fill:#2F2F2F;"/>
<g>
<path d="M1799.01,50.53c-4.56,0.41-6.36,3.04-12.06,3.04v14.68c6.12,0,12.43-3.48,15.53-7.35 C1805.98,56.54,1805.82,49.93,1799.01,50.53z" style="fill:#2F2F2F;"/>
<path d="M1774.89,50.53c4.56,0.41,6.36,3.04,12.06,3.04v14.68c-6.12,0-12.43-3.48-15.53-7.35 C1767.93,56.54,1768.09,49.93,1774.89,50.53z" style="fill:#2F2F2F;"/>
</g>
</g>
<path d="M1949.98,49.04c-0.01-2.6-0.17-5.16-0.47-7.62c-2-16.35-11.24-30.55-24.12-37.07 c-6.06-3.06-12.39-4.29-18.93-3.66c-12.49,1.25-25.33,8.45-32.73,20.82c-17.74,29.67-6.38,65.56-3.38,71.66 c15.34,31.17,40.12,33.83,52.62,32.82c13.58-1.1,29.43-6.61,31.69-12.81c0.53-1.47,0.46-3.06-0.2-4.48 c-1.3-2.75-3.95-2.49-4.82-2.41l-0.99,0.11l-0.26,0.01c-3.78-0.05-5.44-1.02-6.59-3.81c-1.75-4.27-0.31-10.54,1.15-15.52 C1945.94,76.85,1950.05,62.84,1949.98,49.04z" style="fill:#EEEEEE;"/>
<g>
<path d="M1918.63,45.01c1.74-0.29,3.59-0.51,5.37-0.34c1.81,0.19,3.58,1,5.45,0.76 c1.22-0.15,2.53-0.95,3.24-1.86c1.51-1.92,1.66-4.42,0.82-6.6c-0.62-1.57-1.74-2.96-3.25-3.87c-3.71-2.25-9.03-0.83-12.15,1.91 c-3.2,2.8-5.53,7.56-4.02,9.65C1915,45.92,1917.53,45.18,1918.63,45.01z" style="fill:#2F2F2F;"/>
<path d="M1896.98,45.01c-1.74-0.29-3.59-0.51-5.37-0.34c-1.81,0.19-3.58,1-5.45,0.76 c-1.22-0.15-2.53-0.95-3.24-1.86c-1.51-1.92-1.66-4.42-0.82-6.6c0.62-1.57,1.74-2.96,3.25-3.87c3.71-2.25,9.03-0.83,12.15,1.91 c3.2,2.8,5.53,7.56,4.02,9.65C1900.62,45.92,1898.08,45.18,1896.98,45.01z" style="fill:#2F2F2F;"/>
<g>
<path d="M1894.97,68.21c4.56-0.41,6.36-3.04,12.06-3.04V50.49c-6.12,0-12.43,3.48-15.53,7.35 C1888.01,62.21,1888.17,68.82,1894.97,68.21z" style="fill:#2F2F2F;"/>
<path d="M1919.09,68.21c-4.56-0.41-6.36-3.04-12.06-3.04V50.49c6.12,0,12.43,3.48,15.53,7.35 C1926.06,62.21,1925.9,68.82,1919.09,68.21z" style="fill:#2F2F2F;"/>
</g>
</g>
<path d="M1521.1,50.53c-0.01-2.6-0.17-5.16-0.47-7.62c-2-16.35-11.24-30.55-24.12-37.07 c-6.06-3.06-12.39-4.29-18.93-3.66c-12.49,1.25-25.33,8.45-32.73,20.82c-17.74,29.67-6.38,65.56-3.38,71.66 c15.34,31.17,40.12,33.83,52.62,32.82c13.58-1.1,29.43-6.61,31.69-12.81c0.53-1.47,0.46-3.06-0.2-4.48 c-1.3-2.75-3.95-2.49-4.82-2.41l-0.99,0.11l-0.26,0.01c-3.78-0.05-5.44-1.02-6.59-3.81c-1.75-4.27-0.31-10.54,1.15-15.52 C1517.07,78.34,1521.18,64.32,1521.1,50.53z" style="fill:#EEEEEE;"/>
<path d="M1369.79,109.23c2.59-13.72,4.41-27.8,4.7-41.75c0.25-12.21,1.22-24.62,5.55-36.04 c4.33-11.42,12.44-21.87,23.68-26.66c4.59-1.96,9.56-2.79,14.53-2.63v116.37c-1.92,0.03-3.83,0.36-5.63,1.09 c-4.62,1.87-8.32,4.16-13.28,4.54c-4.87,0.37-9.15-3.17-13.94-4.11c-2.9-0.57-5.98-0.14-8.61,1.19c-1.74,0.88-3.28,2.14-5.07,2.9 c-1.79,0.76-4.04,0.94-5.56-0.27C1367.51,119.03,1368.85,114.17,1369.79,109.23z" style="fill:#EEEEEE;"/>
<g>
<path d="M1349.74,59.6c-0.21-3.16-0.49-6.35-1.04-9.41c-1.58-9-7.61-18.28-17.19-20.2 c-6.2-1.24-10.94,2.45-16.61,3.78c-0.18,0.04-1.64-1.44-1.88-1.62c-0.71-0.54-1.46-1.03-2.24-1.47c-1.61-0.93-3.34-1.65-5.11-2.22 c-3.62-1.15-7.49-1.63-11.28-1.35c-3.07,0.22-6.19,0.96-8.85,2.55c-1.21,0.73-2.32,1.64-3.22,2.74c-1.19,1.45-1.6,3.05-2.24,4.79 c-1.49,4.05-5.45,7.08-8.29,10.21c-3.32,3.67-6.72,7.27-10.42,10.56c-7.19,6.39-16.05,10.27-23.56,16.19 c-8.52,6.71-16.59,18.65-14.31,30.06c1.07,5.39,5.97,9.31,10.89,11.25c15.38,6.07,30.93,5.97,47.02,2.69 c8.41-1.72,16.55-4.42,24.65-7.25c7.73-2.7,15.59-5.02,23.21-8.04c6.55-2.59,20.82-7.34,20.79-16.22 C1350.02,77.6,1350.36,68.64,1349.74,59.6z" style="fill:#006CA2;"/>
<path d="M1334.86,45.8c1.06-1.03,2.07-2.29,2.69-3.64c0.2-0.43,0.21-0.96,0.26-1.45 c0.04-0.36,0.1-0.71,0.26-0.98c0.13-0.21,2.49,2.84,2.71,3.2c1.88,3.13,2.12,6.73,2.28,10.29c0.1,2.3-1.09,2.02-2.91,1.85 c-1.46-0.13-2.94-0.16-4.41-0.22c-1.16-0.05-2.32-0.36-2.99-1.37c-0.61-0.91-0.61-2.07-1.04-3.03 C1330.65,48.16,1333.45,47.17,1334.86,45.8z" style="fill:#FFFFFF;"/>
<path d="M1286.94,36.86c5.28-6.3,19.79-3.5,24.17,2.74c0.97,1.38,1.38,3.35,1.08,5 c-0.37,1.98-1.76,2.67-3.39,3.52c-0.67,0.35-1.94,1.45-2.74,1.24c-0.88-0.24-1.26-1.67-1.89-2.26 c-4.24-3.99-10.63-5.25-16.27-5.26c-0.75,0-1.52,0.23-2.25,0.14c-0.31-0.04-0.5-0.2-0.57-0.45 C1284.69,40.37,1286.48,37.39,1286.94,36.86z" style="fill:#40C0E7;"/>
<path d="M1279.45,47.57c0.34-0.53,0.76-0.96,1.26-1.33c0.3-0.22,0.65-0.38,1.02-0.49 c4.15-1.2,9.11,0.36,13.13,1.5c2.59,0.73,10.46,3.23,7.69,7.38c-0.72,1.07-2.17,1.79-3.45,1.72c-1.83-0.1-3.16-1.48-4.71-2.29 c-1.75-0.91-3.46-1.76-5.34-2.4c-1.52-0.53-3.06-1.02-4.63-1.42c-1.36-0.35-2.56-0.29-3.94-0.45c-0.35-0.04-0.64,0.04-0.97-0.13 C1278.78,49.25,1279.1,48.13,1279.45,47.57z" style="fill:#FFFFFF;"/>
<path d="M1272,54.42c1.07-1.33,2.57-1.63,4.14-1.7c0.56-0.03,1.14-0.02,1.71-0.02 c3.44,0,6.85,0.79,9.95,2.3c2.07,1,4.34,2.04,5.83,3.84c0.87,1.05,1.76,2.08,1.35,3.54c-1.33,4.67-7.24-0.64-9.14-1.65 c-1.65-0.86-3.67-1.9-5.44-2.43c-0.9-0.27-1.84-0.33-2.73-0.58c-1.71-0.47-3.34-0.58-5.06-0.84 C1271.13,56.67,1271.25,55.37,1272,54.42z" style="fill:#FFFFFF;"/>
<path d="M1264.3,61.76c0.78-1.33,2.61-1.69,4.01-1.85l0.08,0c2.92-0.3,6.25,0.65,9.04,1.47 c0.97,0.29,2.1,0.57,3.03,0.97c2.02,0.87,4.27,2.07,5.77,3.68c2.28,2.44-0.42,4.36-3.2,4.1c-0.48-0.04-0.85-0.25-1.3-0.39 c-0.68-0.21-1.39-0.26-2.08-0.44c-2.01-0.56-3.86-1.41-5.67-2.41c-0.92-0.51-1.88-0.83-2.87-1.22c-1.18-0.48-2.32-0.82-3.53-1.25 c-0.94-0.34-2.47-0.29-3.27-0.94C1263.85,63.07,1264,62.26,1264.3,61.76z" style="fill:#FFFFFF;"/>
<path d="M1238.42,82.08c1.84-1.79,3.85-3.4,5.91-4.92c2.42-1.77,4.92-3.41,7.44-5.04 c1.28-0.82,2.54-1.65,3.83-2.46c0.86-0.54,1.79-0.87,2.76-1.04c3.15-0.57,6.72,0.52,9.53,1.61c2.14,0.84,4.19,1.89,6.23,2.94 c3.74,1.94,3.36,5.39,3.69,9.16c0.24,2.74,0.37,5.5,0.37,8.25c0,1.38-0.03,2.76-0.1,4.13c-0.1,2.06-0.77,3.65-2.98,4.1 c-1.2,0.24-2.43,0.42-3.64,0.6c-2.4,0.36-4.8,0.63-7.23,0.83c-5.45,0.45-11.08,0.2-16.48-0.74c-3.44-0.6-7-1.51-9.99-3.38 c-2.2-1.37-4.2-3.71-4.14-6.43C1233.69,86.42,1236.25,84.2,1238.42,82.08z" style="fill:#FFFFFF;"/>
<path d="M1341.43,88.37c-4.51,3.56-10.12,5.12-15.36,7.26c-5.81,2.38-11.47,4.88-17.46,6.8 c-6.45,2.08-12.95,4.04-19.37,6.21c-9.43,3.18-19.51,4.99-29.46,4.68c-5.51-0.17-10.98-0.98-16.38-2.14 c-3.43-0.74-6.9-1.99-9.64-4.24c-1.79-1.47-3.32-3.46-4-5.69c-0.34-1.14-0.4-2.32-0.17-3.48c0.44-2.26,1.56-1.72,2.51-0.14 c1.15,1.92,2.86,3.15,4.75,4.27c2.09,1.22,4.36,2.09,6.68,2.76c1.73,0.51,3.5,0.9,5.28,1.22c5.99,1.08,12.1,0.95,18.14,0.39 c11.36-1.05,22.24-4.78,32.74-9.04c3.17-1.28,6.3-2.62,9.45-3.96c5.42-2.31,10.74-4.83,16.12-7.25 c4.97-2.24,10.37-3.85,15.14-6.48c0.62-0.34,1.18-0.99,1.67-0.33c0.65,0.86,0.22,3.49,0.18,4.69v0.14 C1342.25,85.35,1342.59,87.46,1341.43,88.37z" style="fill:#FFFFFF;"/>
<path d="M1343.56,68.43c-0.17,1.93-1.38,2.91-2.98,3.91c-1.94,1.2-3.77,2.51-5.82,3.51 c-4.03,1.97-8.21,3.71-12.33,5.5c-5.3,2.31-10.69,4.44-16.11,6.42c-2.5,0.91-20.04,10.06-21.58,6.76 c-0.32-0.71-0.19-2.25-0.18-3.03c0.01-1.05,0.24-2.14,0.1-3.19c-0.22-1.79-0.36-3.62-0.75-5.38c-0.25-1.13-0.48-2.26-0.88-3.35 c-0.43-1.19-0.84-2.77,0.47-3.58c0.48-0.3,1.28-0.43,1.84-0.5c0.8-0.1,1.55-0.2,2.32-0.5c2.26-0.87,3.63-2.48,4.11-4.85 c0.22-1.11,1.43-0.85,2.27-0.88c0.52-0.02,0.88-0.3,1.34-0.47c1.36-0.5,2.66-1.2,3.59-2.33c0.48-0.57,0.8-1.18,1.04-1.88 c0.31-0.85,0-1.74,0.3-2.55c0.4-1.12,2.82-0.97,3.72-1.42c1.34-0.67,2.49-1.8,3.02-3.2c0.47-1.24-0.01-3.12,1.21-3.98 c0.48-0.34,1.29-0.36,1.85-0.56c1.25-0.44,2.57-1.5,3.94-1.22c1.42,0.29,2.62,0.89,4.12,0.93c1.52,0.04,3.04-0.19,4.52-0.56 c1.14-0.28,2.15-0.9,3.29-1.18c1.8-0.44,1.79,2.18,1.81,3.37c0.03,1.89,1.15,3.6,2.87,4.44c3.88,1.88,9.12,0.24,12.76,2.36 C1343.52,63.49,1343.77,65.98,1343.56,68.43z" style="fill:#40C0E7;"/>
</g>
<g>
<polygon points="1.66,10.5 44.17,1.78 42.31,29.82 " style="fill:#E1F5FE;"/>
<polygon points="20.78,68.9 1.66,10.5 42.31,29.82 " style="fill:#81D4FA;"/>
<polygon points="64.3,63.7 42.31,29.82 20.78,68.9 " style="fill:#64B5F6;"/>
<polygon points="117.5,126.34 126.22,83.83 98.18,85.69 " style="fill:#0288D1;"/>
<polygon points="59.1,107.22 117.5,126.34 98.18,85.69 " style="fill:#81D4FA;"/>
<polygon points="64.3,63.7 98.18,85.69 59.1,107.22 " style="fill:#E1F5FE;"/>
<polygon points="59.1,107.22 64.3,63.7 20.78,68.9 " style="fill:#B2EBF2;"/>
<polygon points="75.95,11.57 116.43,52.05 126.22,83.83 98.18,85.69 64.3,63.7 42.31,29.82 44.17,1.78 " style="fill:#B3E5FC;"/>
<polygon points="2.24,125.76 1.66,10.5 20.78,68.9 " style="fill:#1E88E5;"/>
<polygon points="2.24,125.76 117.5,126.34 59.1,107.22 " style="fill:#B3E5FC;"/>
<polygon points="59.1,107.22 59.1,107.22 2.24,125.76 20.78,68.9 " style="fill:#E1F5FE;"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 78 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" enable-background="new 0 0 64 64"><g fill="#ff9d27"><path d="m10.9 48.7c4-4 4.4-5 6.9-2.5 2.5 2.5 1.5 2.8-2.5 6.9-3 3-6.8 2.4-6.8 2.4s-.6-3.8 2.4-6.8"/><path d="m18.5 52.8c1.6-4.2 2.1-4.7-.2-6-2.3-1.3-2.3-.4-3.8 3.8-1.2 3.1.2 5.9.2 5.9s2.7-.5 3.8-3.7"/></g><path d="m16.2 48.9c.9-2.3.9-2.8 2.1-2.1 1.3.7 1 1 .1 3.3-.6 1.7-2.1 2.1-2.1 2.1s-.7-1.5-.1-3.3" fill="#fdf516"/><path d="m17.1 45.7c-1.3-2.3-1.8-1.8-6-.2-3.1 1.2-3.7 3.8-3.7 3.8s2.8 1.4 5.9.2c4.2-1.6 5.1-1.6 3.8-3.8" fill="#ff9d27"/><g fill="#fdf516"><path d="m15 47.8c2.3-.9 2.8-.9 2.1-2.1-.7-1.3-1-1-3.3-.1-1.7.6-2.1 2.1-2.1 2.1s1.6.7 3.3.1"/><path d="m13.9 47.6c2.2-2.2 2.4-2.8 3.8-1.4 1.4 1.4.8 1.6-1.4 3.8-1.7 1.7-3.8 1.3-3.8 1.3s-.2-2 1.4-3.7"/></g><path d="M18.5,38C12.3,27.6,2,31.9,2,31.9s14.7-14.7,24.6-4.8L18.5,38z" fill="#3baacf"/><path d="m23.3 30.3l3.2-3.2c-9.8-9.9-24.5 4.8-24.5 4.8s12.9-9.2 21.3-1.6" fill="#428bc1"/><path d="M26,45.5C36.4,51.7,32.1,62,32.1,62s14.7-14.7,4.8-24.6L26,45.5z" fill="#3baacf"/><path d="m33.7 40.7l3.2-3.2c9.9 9.9-4.8 24.6-4.8 24.6s9.2-13 1.6-21.4" fill="#428bc1"/><path d="m48.8 30.9c-11.7 11.6-24.6 17.9-29.1 13.4-4.5-4.5 1.8-17.4 13.4-29.1 13.6-13.6 28.7-13 28.7-13s.5 15.1-13 28.7" fill="#c5d0d8"/><path d="M45.8,27.6C34.2,39.2,22.6,46.8,19.9,44.1c-2.7-2.7,4.9-14.3,16.5-25.9C50,4.6,62,2,62,2S59.4,14,45.8,27.6z" fill="#dae3ea"/><path d="m24.3 47.5c-.5.5-1.3.5-1.8 0l-6-6c-.5-.5-.5-1.4 0-1.9l1.8-1.8 7.8 7.8-1.8 1.9" fill="#c94747"/><path d="m22.6 45.7c-.5.5-1.1.7-1.4.4l-3.4-3.4c-.3-.3-.1-.9.4-1.4l1.8-1.8 4.4 4.4-1.8 1.8" fill="#f15744"/><path d="m20.9 48.2c-.3.3-1 .3-1.3 0l-3.9-3.9c-.3-.3-.2-.9.1-1.2l1.2-1.2 5.1 5.1-1.2 1.2" fill="#3e4347"/><path d="m20.1 47.4c-.3.3-.9.4-1.1.2l-2.7-2.7c-.2-.2-.1-.7.3-1l1.2-1.2 3.5 3.5-1.2 1.2" fill="#62727a"/><path d="m61.8 2.2c0 0-5.4-.2-12.7 2.6l10.1 10.1c2.8-7.3 2.6-12.7 2.6-12.7" fill="#c94747"/><path d="m61.8 2.2c0 0-4.3.9-10.8 4.6l6.2 6.2c3.7-6.5 4.6-10.8 4.6-10.8" fill="#f15744"/><circle cx="43.5" cy="20.5" r="5" fill="#edf4f9"/><circle cx="43.5" cy="20.5" r="3.3" fill="#3baacf"/><circle cx="33.5" cy="30.5" r="5" fill="#edf4f9"/><circle cx="33.5" cy="30.5" r="3.3" fill="#3baacf"/><g fill="#fff"><path d="m48.9 6.9c-.3.3-.9.3-1.2 0-.3-.3-.3-.9 0-1.2.3-.3.9-.3 1.2 0 .3.3.3.9 0 1.2"/><circle cx="50.6" cy="8.6" r=".8"/><circle cx="53" cy="11" r=".8"/><circle cx="55.3" cy="13.4" r=".8"/><circle cx="57.7" cy="15.7" r=".8"/></g></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View file

@ -0,0 +1,24 @@
export const environment = {
production: true,
uploadImageHostname: "node.deso.org",
verificationEndpointHostname: "https://node.deso.org",
uploadVideoHostname: "node.deso.org",
identityURL: "https://identity.deso.org",
supportEmail: "node.admin@bitclout.com",
dd: {
apiKey: "DCEB26AC8BF47F1D7B4D87440EDCA6",
jsPath: "https://bitclout.com/tags.js",
ajaxListenerPath: "bitclout.com/api",
endpoint: "https://bitclout.com/js/",
},
amplitude: {
key: "23345b239094949bc7f3402cebe9e5d2",
domain: "amp.bitclout.com",
},
node: {
id: 2,
name: "BitClout",
url: "https://bitclout.com",
logoAssetDir: "/assets/bitclout/",
},
};

View file

@ -0,0 +1,24 @@
export const environment = {
production: true,
uploadImageHostname: "node.deso.org",
verificationEndpointHostname: "https://node.deso.org",
uploadVideoHostname: "node.deso.org",
identityURL: "https://identity.deso.org",
supportEmail: "",
dd: {
apiKey: "DCEB26AC8BF47F1D7B4D87440EDCA6",
jsPath: "https://bitclout.com/tags.js",
ajaxListenerPath: "bitclout.com/api",
endpoint: "https://bitclout.com/js/",
},
amplitude: {
key: "",
domain: "",
},
node: {
id: 1,
name: "DeSo",
url: "https://node.deso.org",
logoAssetDir: "/assets/deso/",
},
};

View file

@ -0,0 +1,28 @@
// This file can be replaced during build by using the `fileReplacements` array.
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`.
export const environment = {
production: false,
uploadImageHostname: "node.deso.org",
verificationEndpointHostname: "https://node.deso.org",
uploadVideoHostname: "node.deso.org",
identityURL: "https://identity.deso.org",
supportEmail: "",
dd: {
apiKey: "DCEB26AC8BF47F1D7B4D87440EDCA6",
jsPath: "https://bitclout.com/tags.js",
ajaxListenerPath: "bitclout.com/api",
endpoint: "https://bitclout.com/js/",
},
amplitude: {
key: "",
domain: "",
},
node: {
id: 1,
name: "DeSo",
url: "https://node.deso.org",
logoAssetDir: "/assets/deso/",
},
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer" />
<title>Welcome to BitClout</title>
<meta name="description" content="BitClout is a platform owned by its users. Bitcoin is decentralizing money, BitClout is decentralizing social media." />
<meta name="theme-color" content="#eeeeee" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#121212" media="(prefers-color-scheme: dark)">
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://bitclout.com/assets/bitclout/camelcase_logo_og.jpg" />
<meta property="og:title" content="Welcome to BitClout" />
<meta property="og:description" content="BitClout is a platform owned by its users. Bitcoin is decentralizing money, BitClout is decentralizing social media." />
<meta property="og:site_name" content="BitClout" />
<meta property='og:image' content="https://bitclout.com/assets/bitclout/camelcase_logo_og.jpg" />
<meta property="og:image:secure_url" content="https://bitclout.com/assets/bitclout/camelcase_logo_og.jpg" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:alt" content="bitclout.com Logo on White Background" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://bitclout.com" />
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=0.9" />
<link rel="icon" type="image/x-icon" href="/assets/bitclout/favicon.png" />
<link href="/vendor/bootstrap.min.css" rel="stylesheet" />
<link href="/vendor/roboto-mono.css" rel="stylesheet" />
<link href="/vendor/roboto.css" rel="stylesheet" />
<link href="/vendor/fontello.css" rel="stylesheet" />
<link href="/vendor/bs-datepicker.css" rel="stylesheet" />
<script src="https://kit.fontawesome.com/070ca4195b.js" crossorigin="anonymous"></script>
<!-- Add to iOS home screen -->
<link rel="manifest" href="/assets/app.webmanifest" />
<script async src="/vendor/pwacompat.min.js" crossorigin="anonymous"></script>
<link rel="icon" type="image/png" href="/assets/bitclout/logo-512.png" sizes="512x512" />
<link rel="icon" type="image/png" href="/assets/bitclout/logo-192.png" sizes="192x192" />
<link rel="apple-touch-icon" sizes="192x192" href="/assets/bitclout/logo-192.png" type="image/png" />
<link rel="apple-touch-icon" sizes="512x512" href="/assets/bitclout/logo-512.png" type="image/png" />
</head>
<body app-theme>
<app-root></app-root>
</body>
</html>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="referrer" content="no-referrer" />
<title>Welcome to DeSo</title>
<meta name="description" content="DeSo is a platform owned by its users. Bitcoin is decentralizing money, DeSo is decentralizing social media." />
<meta name="theme-color" content="#eeeeee" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#121212" media="(prefers-color-scheme: dark)">
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:image" content="https://node.deso.org/assets/deso/camelcase_logo_og.jpg" />
<meta property="og:title" content="Welcome to DeSo" />
<meta property="og:description" content="DeSo is a platform owned by its users. Bitcoin is decentralizing money, DeSo is decentralizing social media." />
<meta property="og:site_name" content="DeSo" />
<meta property='og:image' content="https://node.deso.org/assets/deso/camelcase_logo_og.jpg" />
<meta property="og:image:secure_url" content="https://node.deso.org/assets/deso/camelcase_logo_og.jpg" />
<meta property="og:image:type" content="image/jpeg" />
<meta property="og:image:alt" content="DeSo Logo on White Background" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://node.deso.org" />
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=0.9" />
<link rel="icon" type="image/x-icon" href="/assets/deso/favicon.png" />
<link href="/vendor/bootstrap.min.css" rel="stylesheet" />
<link href="/vendor/roboto-mono.css" rel="stylesheet" />
<link href="/vendor/roboto.css" rel="stylesheet" />
<link href="/vendor/fontello.css" rel="stylesheet" />
<link href="/vendor/bs-datepicker.css" rel="stylesheet" />
<script src="https://kit.fontawesome.com/070ca4195b.js" crossorigin="anonymous"></script>
<!-- Add to iOS home screen -->
<link rel="manifest" href="/assets/app.webmanifest" />
<script async src="/vendor/pwacompat.min.js" crossorigin="anonymous"></script>
<link rel="icon" type="image/png" href="/assets/deso/logo-512.png" sizes="512x512" />
<link rel="icon" type="image/png" href="/assets/deso/logo-192.png" sizes="192x192" />
<link rel="apple-touch-icon" sizes="192x192" href="/assets/deso/logo-192.png" type="image/png" />
<link rel="apple-touch-icon" sizes="512x512" href="/assets/deso/logo-512.png" type="image/png" />
</head>
<body app-theme>
<app-root></app-root>
</body>
</html>

View file

@ -0,0 +1,32 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, '../coverage/electron-angular-app'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
};

View file

@ -0,0 +1,13 @@
import { enableProdMode } from "@angular/core";
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic";
import { AppModule } from "./app/app.module";
import { environment } from "./environments/environment";
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch((err) => console.error(err));

View file

@ -0,0 +1,66 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import "zone.js/dist/zone"; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/
// https://stackoverflow.com/questions/57646823/angular-8-referenceerror-global-is-not-defined-when-im-trying-to-connect-cl
(window as any).global = window;
global.Buffer = global.Buffer || require("buffer").Buffer;
global.process = require("process");

View file

@ -0,0 +1,26 @@
// Adding a SASS file since I don't know how to write the code below in SCSS
$loading-icon-url: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMiAzMiIgd2lkdGg9IjMyIiBoZWlnaHQ9IjMyIiBmaWxsPSIjZjBmMGYwIj4KICA8cGF0aCBvcGFjaXR5PSIuMjUiIGQ9Ik0xNiAwIEExNiAxNiAwIDAgMCAxNiAzMiBBMTYgMTYgMCAwIDAgMTYgMCBNMTYgNCBBMTIgMTIgMCAwIDEgMTYgMjggQTEyIDEyIDAgMCAxIDE2IDQiLz4KICA8cGF0aCBkPSJNMTYgMCBBMTYgMTYgMCAwIDEgMzIgMTYgTDI4IDE2IEExMiAxMiAwIDAgMCAxNiA0eiI+CiAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPSJ0cmFuc2Zvcm0iIHR5cGU9InJvdGF0ZSIgZnJvbT0iMCAxNiAxNiIgdG89IjM2MCAxNiAxNiIgZHVyPSIwLjhzIiByZXBlYXRDb3VudD0iaW5kZWZpbml0ZSIgLz4KICA8L3BhdGg+Cjwvc3ZnPgo=)
//$button-gradient: linear-gradient(180deg, $color 14.13%, lighten(saturate($color, 20), 5) 97.78%)
.btn-loading
position: relative
color: transparent !important
pointer-events: none
cursor: default
background-repeat: no-repeat
background-position: center
background-size: auto 40%, auto
background-image: $loading-icon-url //, $button-gradient
opacity: 0.4
.follow-button__link-loading
position: relative
color: transparent !important
pointer-events: none
cursor: default
background-repeat: no-repeat
background-position: center
background-size: auto 40%, auto
background-image: $loading-icon-url //, $button-gradient
opacity: 0.4

View file

View file

@ -0,0 +1,14 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import "zone.js/dist/zone-testing";
import { getTestBed } from "@angular/core/testing";
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from "@angular/platform-browser-dynamic/testing";
declare const require: any;
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting());
// Then we find all the tests.
const context = require.context("./", true, /\.spec\.ts$/);
// And load the modules.
context.keys().map(context);

View file

@ -0,0 +1,14 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"types": ["node"]
},
"files": [
"main.ts",
"polyfills.ts"
],
"include": [
"src/**/*.d.ts"
]
}

View file

@ -0,0 +1,19 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"types": [
"jasmine",
"node",
"jest"
]
},
"files": [
"test.ts",
"polyfills.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View file

@ -0,0 +1,63 @@
$dark-color: #ffffff;
$light-color: #333333;
$light-gray: #ecf0f1;
$light-hover-color: #bababa;
$dark-in-between-color: #d4d4d4;
$separating-line-color: #777777;
$hardcore-text-color: var(--on-primary) !important;
$important-text-color: #333333;
$placeholder-color: #969da2;
$text-color: var(--on-primary) !important;
$error-color: #FF3636;
$good-color: #24cc40;
$yellow-color: #24cc40;
$translucent-modal-background: #979797a6;
$button-font-size: 1rem;
$button-height: 3rem;
$normal-text-size: 1.25rem;
$big-text-size: 1.5rem;
$border-color: #d4d4d4;
$button-color-default: #0059F7;
$button-hover-color-default: #0059F7;
$button-text-color-default: white;
$button-color-pressed-default: #60a3de;
$stake-button-color: #24cc40;
$sidebar-value-color: #0059F7;
$tooltip-color: #FF3636;
$bad-color: #FF3636;
$x-color: #FF3636;
$important-button: #24cc40;
$profile-button: #f79400;
$core-post-color: #333333;
$comment-color: #0059F7;
$comment-hover: rgba(75, 181, 214, 0.158);
$post-text-color: white;
$grey: #a8a8a8;
$repost-color: green;
$repost-hover: #24cc4034;
$like-color: #FF3636;
$like-hover: #ff36362d;
$diamond-color: #0059F7;
$diamond-hover: #005bf734;
$link-btn-color: #0059F7;
$link-btn-hover:rgba(75, 181, 214, 0.158);
//#212529
//p
//background-color: #6FCF97;
//background-color: #18A0FB;
//background-color: #EF8275;
//background-color: #6FCF97;
//background-color: #ce6060;

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,672 @@
/* .bs-datepicker */
.bs-datepicker {
display: flex;
align-items: stretch;
flex-flow: row wrap;
background: #fff;
box-shadow: 0 0 10px 0 #aaa;
position: relative;
z-index: 1;
/* button */
/* .bs-datepicker-head */
/* .bs-datepicker-body */
/* .current-timedate */
/* .bs-datepicker-multiple */
/* .bs-datepicker-btns */
/*.bs-datepicker-custom-range */
/* .bs-datepicker-predefined-btns */
/* .bs-datepicker-buttons */
}
.bs-datepicker:after {
clear: both;
content: "";
display: block;
}
.bs-datepicker bs-day-picker {
float: left;
}
.bs-datepicker button:hover,
.bs-datepicker button:focus,
.bs-datepicker button:active,
.bs-datepicker input:hover,
.bs-datepicker input:focus,
.bs-datepicker input:active, .bs-datepicker-btns button:hover, .bs-datepicker-btns button:focus, .bs-datepicker-btns button:active, .bs-datepicker-predefined-btns button:active, .bs-datepicker-predefined-btns button:focus {
outline: none;
}
.bs-datepicker-head {
min-width: 270px;
height: 50px;
padding: 10px;
border-radius: 3px 3px 0 0;
text-align: justify;
/* .bs-datepicker-head button */
}
.bs-datepicker-head:after {
content: "";
display: inline-block;
vertical-align: top;
width: 100%;
}
.bs-datepicker-head button {
display: inline-block;
vertical-align: top;
padding: 0;
height: 30px;
line-height: 30px;
border: 0;
background: transparent;
text-align: center;
cursor: pointer;
color: #fff;
transition: 0.3s;
}
.bs-datepicker-head button[disabled], .bs-datepicker-head button[disabled]:hover, .bs-datepicker-head button[disabled]:active {
background: rgba(221, 221, 221, 0.3);
color: #f5f5f5;
cursor: not-allowed;
}
.bs-datepicker-head button.previous span {
transform: translate(-1px, -1px);
}
.bs-datepicker-head button.next span {
transform: translate(1px, -1px);
}
.bs-datepicker-head button.next, .bs-datepicker-head button.previous {
border-radius: 50%;
width: 30px;
height: 30px;
}
.bs-datepicker-head button.next span, .bs-datepicker-head button.previous span {
font-size: 28px;
line-height: 1;
display: inline-block;
position: relative;
height: 100%;
width: 100%;
border-radius: 50%;
}
.bs-datepicker-head button.current {
border-radius: 15px;
max-width: 155px;
padding: 0 13px;
}
.bs-datepicker-head button:hover {
background-color: rgba(0, 0, 0, 0.1);
}
.bs-datepicker-head button:active {
background-color: rgba(0, 0, 0, 0.2);
}
.bs-datepicker-body {
padding: 10px;
border-radius: 0 0 3px 3px;
min-height: 232px;
min-width: 278px;
border: 1px solid #e9edf0;
/* .bs-datepicker-body table */
}
.bs-datepicker-body .days.weeks {
position: relative;
z-index: 1;
}
.bs-datepicker-body table {
width: 100%;
border-collapse: separate;
border-spacing: 0;
/* .bs-datepicker-body table.days */
/* .bs-datepicker-body table.weeks */
}
.bs-datepicker-body table th {
font-size: 13px;
color: #9aaec1;
font-weight: 400;
text-align: center;
}
.bs-datepicker-body table td {
color: #54708b;
text-align: center;
position: relative;
padding: 0;
/* todo: check first :not(.disabled) usage */
}
.bs-datepicker-body table td span {
display: block;
margin: 0 auto;
font-size: 13px;
border-radius: 50%;
/*z-index: 1;*/
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.bs-datepicker-body table td:not(.disabled):not(.week) span:not(.disabled):not(.is-other-month) {
cursor: pointer;
}
.bs-datepicker-body table td.is-highlighted:not(.disabled):not(.selected) span,
.bs-datepicker-body table td span.is-highlighted:not(.disabled):not(.selected) {
background-color: #e9edf0;
transition: 0s;
}
.bs-datepicker-body table td.is-active-other-month:not(.disabled):not(.selected) span,
.bs-datepicker-body table td span.is-active-other-month:not(.disabled):not(.selected) {
background-color: #e9edf0;
transition: 0s;
cursor: pointer;
}
.bs-datepicker-body table td span.disabled, .bs-datepicker-body table td.disabled span {
color: #9aaec1;
}
.bs-datepicker-body table td span.selected, .bs-datepicker-body table td.selected span {
color: #fff;
}
.bs-datepicker-body table td span.is-other-month, .bs-datepicker-body table td.is-other-month span {
color: rgba(0, 0, 0, 0.25);
}
.bs-datepicker-body table td.active {
position: relative;
}
.bs-datepicker-body table td.active.select-start:before {
left: 35%;
}
.bs-datepicker-body table td.active.select-end:before {
left: -85%;
}
.bs-datepicker-body table td span.active.select-start:after,
.bs-datepicker-body table td span.active.select-end:after, .bs-datepicker-body table td.active.select-start span:after, .bs-datepicker-body table td.active.select-end span:after {
content: "";
display: block;
position: absolute;
z-index: -1;
width: 100%;
height: 100%;
transition: 0.3s;
top: 0;
border-radius: 50%;
}
.bs-datepicker-body table td:before,
.bs-datepicker-body table td span:before {
content: "";
display: block;
position: absolute;
z-index: -1;
top: 6px;
bottom: 6px;
left: -3px;
right: -2px;
box-sizing: content-box;
background: transparent;
}
.bs-datepicker-body table td.active.select-start + td.active:before {
left: -20%;
}
.bs-datepicker-body table td:last-child.active:before {
border-radius: 0 3px 3px 0;
width: 125%;
left: -25%;
}
.bs-datepicker-body table td span[class*=select-], .bs-datepicker-body table td[class*=select-] span {
border-radius: 50%;
color: #fff;
}
.bs-datepicker-body table.days td.active:not(.select-start):before, .bs-datepicker-body table.days td.in-range:not(.select-start):before,
.bs-datepicker-body table.days span.active:not(.select-start):before,
.bs-datepicker-body table.days span.in-range:not(.select-start):before {
background: #e9edf0;
}
.bs-datepicker-body table.days span {
width: 32px;
height: 32px;
line-height: 32px;
}
.bs-datepicker-body table.days span.select-start {
z-index: 2;
}
.bs-datepicker-body table.days span.is-highlighted.in-range:before {
right: 3px;
left: 0;
}
.bs-datepicker-body table.days span.in-range.select-end:before {
right: 4px;
left: 0;
}
.bs-datepicker-body table.days td.select-start + td.select-end:before, .bs-datepicker-body table.days td.select-start + td.is-highlighted:before, .bs-datepicker-body table.days td.active + td.is-highlighted:before, .bs-datepicker-body table.days td.active + td.select-end:before, .bs-datepicker-body table.days td.in-range + td.is-highlighted:before, .bs-datepicker-body table.days td.in-range + td.select-end:before {
background: #e9edf0;
width: 100%;
}
.bs-datepicker-body table.weeks tr td:nth-child(2).active:before {
border-radius: 3px 0 0 3px;
left: 0;
width: 100%;
}
.bs-datepicker-body table:not(.weeks) tr td:first-child:before {
border-radius: 3px 0 0 3px;
}
.bs-datepicker-body table.years td span {
width: 46px;
height: 46px;
line-height: 45px;
margin: 0 auto;
}
.bs-datepicker-body table.years tr:not(:last-child) td span {
margin-bottom: 8px;
}
.bs-datepicker-body table.months td {
height: 52px;
}
.bs-datepicker-body table.months td span {
padding: 6px;
border-radius: 15px;
}
.bs-datepicker .current-timedate {
color: #54708b;
font-size: 15px;
text-align: center;
height: 30px;
line-height: 30px;
border-radius: 20px;
border: 1px solid #e9edf0;
margin-bottom: 10px;
cursor: pointer;
text-transform: uppercase;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.bs-datepicker .current-timedate span:not(:empty):before {
content: "";
width: 15px;
height: 16px;
display: inline-block;
margin-right: 4px;
vertical-align: text-bottom;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAQCAYAAADJViUEAAABMklEQVQoU9VTwW3CQBCcOUgBtEBKSAukAnBKME+wFCAlYIhk8sQlxFABtJAScAsuAPBEewYcxCP8ouxrPDsza61uiVN1o6RNHD4htSCmq49RfO71BvMJqBBkITRf1kmUW49nQRC9h1I5AZlBClaL8aP1fKgOOxCx8aSLs+Q19eZuNO8QmPqJRtDFguy7OAcDbJPs+/BKVPDIPrvD2ZJgWAmVe7O0rI0Vqs1seyWUXpuJoppYCa5L+U++NpNPkr5OE2oMdARsb3gykJT5ydZcL8Z9Ww60nxg2LhjON9li9OwXZzo+xLbp3nC2s9CL2RrueGyVrgwNm8HpsCzZ9EEW6kqXlo1GQe03FzP/7W8Hl0dBtu7Bf7zt6mIwvX1RvzDCm7+q3mAW0Dl/GPdUCeXrZLT9BrDrGkm4qlPvAAAAAElFTkSuQmCC);
}
.bs-datepicker-multiple {
border-radius: 4px 0 0 4px;
}
.bs-datepicker-multiple + .bs-datepicker-multiple {
margin-left: 10px;
}
.bs-datepicker-multiple .bs-datepicker {
box-shadow: none;
position: relative;
}
.bs-datepicker-multiple .bs-datepicker:not(:last-child) {
padding-right: 10px;
}
.bs-datepicker-multiple .bs-datepicker + .bs-datepicker:after {
content: "";
display: block;
width: 14px;
height: 10px;
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAKCAYAAABrGwT5AAAA1ElEQVQoU42RsQrCUAxF77VuDu7O4oMWW//BURBBpZvgKk4uIrjoqKOTf+DopIO4uYggtFTfw3+pkQqCW1/G5J7kJiFy4m5MxUlxAzgIPHX+lzMPzupRYlYgxiR7vqsOP8YKzsTx0yxFMCUZ+q7aZzlr+OvgoWcAFyAHgat2jLWu48252DdqAihDJGSSJNUUxYmQjs3+hPQBlAh2rG2LCOPnaw3IiGDX99TRCs7ASJsNhUOA7d/LcuHvRG22FIZvsNXw1MX6VZExCilOQKEfeLXr/10+aC9Ho7arh7oAAAAASUVORK5CYII=);
position: absolute;
top: 25px;
left: -8px;
}
.bs-datepicker-multiple .bs-datepicker .left {
float: left;
}
.bs-datepicker-multiple .bs-datepicker .right {
float: right;
}
.bs-datepicker-container {
padding: 15px;
}
.bs-datepicker .bs-media-container {
display: flex;
}
@media (max-width: 768px) {
.bs-datepicker .bs-media-container {
flex-direction: column;
}
}
.bs-datepicker-custom-range {
padding: 15px;
background: #eee;
}
.bs-datepicker-predefined-btns button {
width: 100%;
display: block;
height: 30px;
background-color: #9aaec1;
border-radius: 4px;
color: #fff;
border: 0;
margin-bottom: 10px;
padding: 0 18px;
text-align: left;
transition: 0.3s;
}
.bs-datepicker-predefined-btns button:hover {
background-color: #54708b;
}
.bs-datepicker-buttons {
display: flex;
flex-flow: row wrap;
justify-content: flex-end;
padding-top: 10px;
border-top: 1px solid #e9edf0;
}
.bs-datepicker-buttons .btn-default {
margin-left: 10px;
}
.bs-datepicker-buttons .btn-today-wrapper {
display: flex;
flex-flow: row wrap;
}
.bs-datepicker-buttons .clear-right,
.bs-datepicker-buttons .today-right {
flex-grow: 0;
}
.bs-datepicker-buttons .clear-left,
.bs-datepicker-buttons .today-left {
flex-grow: 1;
}
.bs-datepicker-buttons .clear-center,
.bs-datepicker-buttons .today-center {
flex-grow: 0.5;
}
/* .bs-timepicker */
.bs-timepicker-container {
padding: 10px 0;
}
.bs-timepicker-label {
color: #54708b;
margin-bottom: 10px;
}
.bs-timepicker-controls {
display: inline-block;
vertical-align: top;
margin-right: 10px;
}
.bs-timepicker-controls button {
width: 20px;
height: 20px;
border-radius: 50%;
border: 0;
background-color: #e9edf0;
color: #54708b;
font-size: 16px;
font-weight: 700;
vertical-align: middle;
line-height: 0;
padding: 0;
transition: 0.3s;
}
.bs-timepicker-controls button:hover {
background-color: #d5dadd;
}
.bs-timepicker-controls input {
width: 35px;
height: 25px;
border-radius: 13px;
text-align: center;
border: 1px solid #e9edf0;
}
.bs-timepicker .switch-time-format {
text-transform: uppercase;
min-width: 54px;
height: 25px;
border-radius: 20px;
border: 1px solid #e9edf0;
background: #fff;
color: #54708b;
font-size: 13px;
}
.bs-timepicker .switch-time-format img {
vertical-align: initial;
margin-left: 4px;
}
bs-datepicker-container,
bs-daterangepicker-container {
z-index: 1080;
}
/* screen size < 1024px */
@media (max-width: 768px) {
.bs-datepicker-multiple {
display: flex;
}
.bs-datepicker-multiple + .bs-datepicker-multiple {
margin-top: 10px;
margin-left: 0;
}
}
/* theming */
.theme-default .bs-datepicker-head {
background-color: #777;
}
.theme-default .btn-today-wrapper .btn-success, .theme-default .btn-clear-wrapper .btn-success {
background-color: #777;
border-color: #777;
}
.theme-default .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active:focus, .theme-default .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active:focus {
box-shadow: none;
}
.theme-default .btn-today-wrapper .btn-success:focus, .theme-default .btn-clear-wrapper .btn-success:focus {
box-shadow: none;
}
.theme-default .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active, .theme-default .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active {
background-color: #616161;
border-color: #616161;
}
.theme-default .btn-today-wrapper .btn-success:hover, .theme-default .btn-clear-wrapper .btn-success:hover {
background-color: #6F6E6E;
border-color: #6F6E6E;
}
.theme-default .bs-datepicker-predefined-btns button.selected {
background-color: #777;
}
.theme-default .bs-datepicker-body table td span.selected, .theme-default .bs-datepicker-body table td.selected span,
.theme-default .bs-datepicker-body table td span[class*=select-]:after, .theme-default .bs-datepicker-body table td[class*=select-] span:after {
background-color: #777;
}
.theme-default .bs-datepicker-body table td.week span {
color: #777;
}
.theme-default .bs-datepicker-body table td.active-week span:hover {
cursor: pointer;
background-color: #777;
color: #fff;
opacity: 0.5;
transition: 0s;
}
.theme-green .bs-datepicker-head {
background-color: #5cb85c;
}
.theme-green .btn-today-wrapper .btn-success, .theme-green .btn-clear-wrapper .btn-success {
background-color: #5cb85c;
border-color: #5cb85c;
}
.theme-green .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active:focus, .theme-green .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active:focus {
box-shadow: none;
}
.theme-green .btn-today-wrapper .btn-success:focus, .theme-green .btn-clear-wrapper .btn-success:focus {
box-shadow: none;
}
.theme-green .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active, .theme-green .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active {
background-color: #1e7e34;
border-color: #1e7e34;
}
.theme-green .btn-today-wrapper .btn-success:hover, .theme-green .btn-clear-wrapper .btn-success:hover {
background-color: #218838;
border-color: #218838;
}
.theme-green .bs-datepicker-predefined-btns button.selected {
background-color: #5cb85c;
}
.theme-green .bs-datepicker-body table td span.selected, .theme-green .bs-datepicker-body table td.selected span,
.theme-green .bs-datepicker-body table td span[class*=select-]:after, .theme-green .bs-datepicker-body table td[class*=select-] span:after {
background-color: #5cb85c;
}
.theme-green .bs-datepicker-body table td.week span {
color: #5cb85c;
}
.theme-green .bs-datepicker-body table td.active-week span:hover {
cursor: pointer;
background-color: #5cb85c;
color: #fff;
opacity: 0.5;
transition: 0s;
}
.theme-blue .bs-datepicker-head {
background-color: #5bc0de;
}
.theme-blue .btn-today-wrapper .btn-success, .theme-blue .btn-clear-wrapper .btn-success {
background-color: #5bc0de;
border-color: #5bc0de;
}
.theme-blue .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active:focus, .theme-blue .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active:focus {
box-shadow: none;
}
.theme-blue .btn-today-wrapper .btn-success:focus, .theme-blue .btn-clear-wrapper .btn-success:focus {
box-shadow: none;
}
.theme-blue .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active, .theme-blue .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active {
background-color: #2AA8CD;
border-color: #2AA8CD;
}
.theme-blue .btn-today-wrapper .btn-success:hover, .theme-blue .btn-clear-wrapper .btn-success:hover {
background-color: #3AB3D7;
border-color: #3AB3D7;
}
.theme-blue .bs-datepicker-predefined-btns button.selected {
background-color: #5bc0de;
}
.theme-blue .bs-datepicker-body table td span.selected, .theme-blue .bs-datepicker-body table td.selected span,
.theme-blue .bs-datepicker-body table td span[class*=select-]:after, .theme-blue .bs-datepicker-body table td[class*=select-] span:after {
background-color: #5bc0de;
}
.theme-blue .bs-datepicker-body table td.week span {
color: #5bc0de;
}
.theme-blue .bs-datepicker-body table td.active-week span:hover {
cursor: pointer;
background-color: #5bc0de;
color: #fff;
opacity: 0.5;
transition: 0s;
}
.theme-dark-blue .bs-datepicker-head {
background-color: #337ab7;
}
.theme-dark-blue .btn-today-wrapper .btn-success, .theme-dark-blue .btn-clear-wrapper .btn-success {
background-color: #337ab7;
border-color: #337ab7;
}
.theme-dark-blue .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active:focus, .theme-dark-blue .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active:focus {
box-shadow: none;
}
.theme-dark-blue .btn-today-wrapper .btn-success:focus, .theme-dark-blue .btn-clear-wrapper .btn-success:focus {
box-shadow: none;
}
.theme-dark-blue .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active, .theme-dark-blue .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active {
background-color: #266498;
border-color: #266498;
}
.theme-dark-blue .btn-today-wrapper .btn-success:hover, .theme-dark-blue .btn-clear-wrapper .btn-success:hover {
background-color: #2C6FA9;
border-color: #2C6FA9;
}
.theme-dark-blue .bs-datepicker-predefined-btns button.selected {
background-color: #337ab7;
}
.theme-dark-blue .bs-datepicker-body table td span.selected, .theme-dark-blue .bs-datepicker-body table td.selected span,
.theme-dark-blue .bs-datepicker-body table td span[class*=select-]:after, .theme-dark-blue .bs-datepicker-body table td[class*=select-] span:after {
background-color: #337ab7;
}
.theme-dark-blue .bs-datepicker-body table td.week span {
color: #337ab7;
}
.theme-dark-blue .bs-datepicker-body table td.active-week span:hover {
cursor: pointer;
background-color: #337ab7;
color: #fff;
opacity: 0.5;
transition: 0s;
}
.theme-red .bs-datepicker-head {
background-color: #d9534f;
}
.theme-red .btn-today-wrapper .btn-success, .theme-red .btn-clear-wrapper .btn-success {
background-color: #d9534f;
border-color: #d9534f;
}
.theme-red .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active:focus, .theme-red .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active:focus {
box-shadow: none;
}
.theme-red .btn-today-wrapper .btn-success:focus, .theme-red .btn-clear-wrapper .btn-success:focus {
box-shadow: none;
}
.theme-red .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active, .theme-red .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active {
background-color: #D23531;
border-color: #D23531;
}
.theme-red .btn-today-wrapper .btn-success:hover, .theme-red .btn-clear-wrapper .btn-success:hover {
background-color: #E33732;
border-color: #E33732;
}
.theme-red .bs-datepicker-predefined-btns button.selected {
background-color: #d9534f;
}
.theme-red .bs-datepicker-body table td span.selected, .theme-red .bs-datepicker-body table td.selected span,
.theme-red .bs-datepicker-body table td span[class*=select-]:after, .theme-red .bs-datepicker-body table td[class*=select-] span:after {
background-color: #d9534f;
}
.theme-red .bs-datepicker-body table td.week span {
color: #d9534f;
}
.theme-red .bs-datepicker-body table td.active-week span:hover {
cursor: pointer;
background-color: #d9534f;
color: #fff;
opacity: 0.5;
transition: 0s;
}
.theme-orange .bs-datepicker-head {
background-color: #f0ad4e;
}
.theme-orange .btn-today-wrapper .btn-success, .theme-orange .btn-clear-wrapper .btn-success {
background-color: #f0ad4e;
border-color: #f0ad4e;
}
.theme-orange .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active:focus, .theme-orange .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active:focus {
box-shadow: none;
}
.theme-orange .btn-today-wrapper .btn-success:focus, .theme-orange .btn-clear-wrapper .btn-success:focus {
box-shadow: none;
}
.theme-orange .btn-today-wrapper .btn-success:not(:disabled):not(.disabled):active, .theme-orange .btn-clear-wrapper .btn-success:not(:disabled):not(.disabled):active {
background-color: #ED9C29;
border-color: #ED9C29;
}
.theme-orange .btn-today-wrapper .btn-success:hover, .theme-orange .btn-clear-wrapper .btn-success:hover {
background-color: #FFAC35;
border-color: #FFAC35;
}
.theme-orange .bs-datepicker-predefined-btns button.selected {
background-color: #f0ad4e;
}
.theme-orange .bs-datepicker-body table td span.selected, .theme-orange .bs-datepicker-body table td.selected span,
.theme-orange .bs-datepicker-body table td span[class*=select-]:after, .theme-orange .bs-datepicker-body table td[class*=select-] span:after {
background-color: #f0ad4e;
}
.theme-orange .bs-datepicker-body table td.week span {
color: #f0ad4e;
}
.theme-orange .bs-datepicker-body table td.active-week span:hover {
cursor: pointer;
background-color: #f0ad4e;
color: #fff;
opacity: 0.5;
transition: 0s;
}
/*# sourceMappingURL=bs-datepicker.css.map */

View file

@ -0,0 +1,73 @@
@font-face {
font-family: 'fontello';
src: url('../vendor/fontello.eot?81413070');
src: url('../vendor/fontello.eot?81413070#iefix') format('embedded-opentype'),
url('../vendor/fontello.woff2?81413070') format('woff2'),
url('../vendor/fontello.woff?81413070') format('woff'),
url('../vendor/fontello.ttf?81413070') format('truetype'),
url('../vendor/fontello.svg?81413070#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
/*
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
src: url('../font/fontello.svg?81413070#fontello') format('svg');
}
}
*/
[class^="icon-"]:before, [class*=" icon-"]:before {
font-family: "fontello";
font-style: normal;
font-weight: normal;
speak: never;
display: inline-block;
text-decoration: inherit;
width: 1em;
margin-right: .2em;
text-align: center;
/* opacity: .8; */
/* For safety - reset parent styles, that can break glyph codes*/
font-variant: normal;
text-transform: none;
/* fix buttons height, for twitter bootstrap */
line-height: 1em;
/* Animation center compensation - margins should be symmetric */
/* remove if not needed */
margin-left: .2em;
/* you can be more comfortable with increased icons size */
/* font-size: 120%; */
/* Font smoothing. That was taken from TWBS */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
/* Uncomment for 3D effect */
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
.icon-close:before { content: '\e800'; } /* '' */
.icon-down-arrow:before { content: '\e801'; } /* '' */
.icon-heart:before { content: '\e802'; } /* '' */
.icon-heart-fill:before { content: '\e803'; } /* '' */
.icon-home:before { content: '\e804'; } /* '' */
.icon-link:before { content: '\e805'; } /* '' */
.icon-loading:before { content: '\e806'; } /* '' */
.icon-messages:before { content: '\e807'; } /* '' */
.icon-notifications:before { content: '\e808'; } /* '' */
.icon-reply:before { content: '\e809'; } /* '' */
.icon-repost:before { content: '\e80a'; } /* '' */
.icon-search:before { content: '\e80b'; } /* '' */
.icon-up-arrow:before { content: '\e80c'; } /* '' */
.icon-wallet:before { content: '\e80d'; } /* '' */
.icon-diamond-1:before { content: '\e80e'; } /* '' */
.icon-diamond:before { content: '\f219'; } /* '' */

BIN
example/frontend/src/vendor/fontello.eot vendored Normal file

Binary file not shown.

View file

@ -0,0 +1,218 @@
{
"name": "",
"css_prefix_text": "icon-",
"css_use_suffix": false,
"hinting": true,
"units_per_em": 1000,
"ascent": 850,
"glyphs": [
{
"uid": "515dd3f32642f6f5b3bfc4de2b3c036c",
"css": "close",
"code": 59392,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M526.6 500L778.3 248.3A18.8 18.8 0 1 0 751.7 221.7L500 473.4 248.3 221.7A18.8 18.8 0 0 0 221.7 248.3L473.4 500 221.7 751.7A18.8 18.8 0 0 0 248.3 778.3L500 526.6 751.7 778.3A18.8 18.8 0 0 0 778.3 751.7Z",
"width": 1000
},
"search": [
"close"
]
},
{
"uid": "ed20cb7fd5e5114fc42be6882a98a91f",
"css": "wallet",
"code": 59405,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M710.1 515.1A60 60 0 1 0 770.1 575.1 60 60 0 0 0 710.1 515.1ZM812.7 284.5V248.2A114.7 114.7 0 0 0 679.2 135L190 216C133.1 225.4 88.5 271.4 88.5 320.6V760.4A106.2 106.2 0 0 0 194.7 866.5H805.4A106.2 106.2 0 0 0 911.5 760.4V389.9C911.5 333.8 867.8 288.3 812.7 284.5ZM197 257.9L686.2 176.9A72.3 72.3 0 0 1 770.3 248.2V283.7H194.7A105.6 105.6 0 0 0 135.5 301.8C145.1 280.8 169.3 262.4 197 257.9ZM869 760.4A63.8 63.8 0 0 1 805.3 824.1H194.7A63.8 63.8 0 0 1 131 760.4V389.9A63.7 63.7 0 0 1 194.7 326.2H805.4A63.7 63.7 0 0 1 869 389.9Z",
"width": 1000
},
"search": [
"wallet"
]
},
{
"uid": "3bab3f532746704431d542302a237df7",
"css": "down-arrow",
"code": 59393,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M500 633.8C482 633.8 464.6 625.5 452.3 611L281.6 409.9A26.5 26.5 0 0 1 322.1 375.6L492.8 576.7C495.8 580.3 504.1 580.4 507.2 576.7L677.9 375.6A26.5 26.5 0 0 1 718.4 409.9L547.7 611C535.4 625.5 518 633.8 500 633.8Z",
"width": 1000
},
"search": [
"down-arrow"
]
},
{
"uid": "a8c1d5759c5965393afb227a8d607625",
"css": "up-arrow",
"code": 59404,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M986.6 237.2A21.3 21.3 0 0 0 967 224.1H712.3A21.2 21.2 0 0 0 712.3 266.5H915.7L576.5 605.8A18.1 18.1 0 0 1 550.9 605.8L394.2 449.1A60.5 60.5 0 0 0 308.6 449.1L18 739.7A21.2 21.2 0 1 0 48 769.7L338.6 479.1A18.1 18.1 0 0 1 364.2 479.1L520.9 635.8A60.5 60.5 0 0 0 606.5 635.8L945.8 296.5V500A21.2 21.2 0 1 0 988.2 500V245.3A21.3 21.3 0 0 0 986.6 237.2Z",
"width": 1000
},
"search": [
"up-arrow"
]
},
{
"uid": "edbe10c4dd22514574cddb72418b087e",
"css": "heart",
"code": 59394,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M499.7 818.4A83.5 83.5 0 0 1 442 795.3L438.7 792.1C265.7 627.4 152.5 519.8 157.4 380.1 159.5 315.6 190.9 255.4 241.4 219.1 332 154.1 437.2 181.2 500 242.1 562.7 181.4 667.9 154.3 758.6 219.1L758.6 219.1C809 255.3 840.5 315.4 842.6 379.8 847.2 520 733.4 628.1 561.2 791.6L557.7 795A83.4 83.4 0 0 1 499.7 818.4ZM355 224.2C325.4 224.2 294.8 233 266.2 253.6 226.3 282.3 201.5 330.1 199.8 381.6 195.6 502.2 303.2 604.6 466.1 759.6L471.4 764.7C487.6 780.1 512.1 780 528.4 764.3L532 760.8C695.9 605.2 804.1 502.4 800.3 381.2 798.6 330.7 773.1 281.8 733.9 253.6 655.8 197.8 563.5 229.1 516.5 286.8L500 307 483.5 286.8C453.7 250.2 405.8 224.2 355 224.2Z",
"width": 1000
},
"search": [
"heart"
]
},
{
"uid": "b0c3c776f19866c82080693f720bcb5b",
"css": "heart-fill",
"code": 59395,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M746.3 236.2C661.4 175.6 556.6 203.9 500 273.3 443.4 203.9 338.6 175.3 253.7 236.2 208.7 268.5 180.4 323.1 178.5 380.7 174 511.4 284.6 616.1 453.4 776.8L456.6 779.8A62 62 0 0 0 543.1 779.4L546.6 776C715.4 615.8 825.7 511 821.5 380.3 819.6 323.1 791.3 268.5 746.3 236.2Z",
"width": 1000
},
"search": [
"heart-fill"
]
},
{
"uid": "dc362bc92ace0d5b9df0dcd5142ae9cd",
"css": "home",
"code": 59396,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M823.5 313.5L536.1 138.2A76.2 76.2 0 0 0 463.9 138.2L176.5 313.5C147.2 329 129 358.2 129 389.6V828.5C129 851.9 149 870.9 173.6 870.9H343.5A53.1 53.1 0 0 0 396.6 817.9V628.9C396.6 578.2 443 537 500 537S603.4 578.2 603.4 628.8V817.8A53.1 53.1 0 0 0 656.5 870.9H826.4C851 870.9 871 851.9 871 828.5V389.6C871 358.2 852.8 329 823.5 313.5ZM828.6 815.1A13.4 13.4 0 0 1 815.2 828.5L656.5 828.5A10.6 10.6 0 0 1 645.9 817.9V628.9C645.9 554.9 580.5 494.6 500 494.6S354.1 554.8 354.1 628.9V817.9A10.6 10.6 0 0 1 343.5 828.5L184.8 828.5A13.4 13.4 0 0 1 171.5 815.1V389.6C171.5 374 181 359.2 197.5 350.4L484.9 175.1A32.9 32.9 0 0 1 515.1 175.1L802.5 350.4C819 359.2 828.6 374 828.6 389.6Z",
"width": 1000
},
"search": [
"home"
]
},
{
"uid": "3a7dd2d172ec4fb593777e06b46453bd",
"css": "link",
"code": 59397,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M708.9 733.5H599.9A21.2 21.2 0 0 1 599.9 691H708.9C814.3 691 899.9 605.3 899.9 500S814.2 309 708.9 309H599.9A21.2 21.2 0 0 1 599.9 266.6H708.9C837.6 266.6 942.4 371.4 942.4 500.1S837.6 733.5 708.9 733.5ZM421.3 712.3A21.2 21.2 0 0 0 400.1 691H291.1C185.8 691 100.1 605.3 100.1 500S185.8 309 291.1 309H400.1A21.2 21.2 0 0 0 400.1 266.6H291.1C162.3 266.5 57.6 371.3 57.6 500S162.3 733.5 291.1 733.5H400.1A21.2 21.2 0 0 0 421.3 712.3ZM702.8 504.7A21.2 21.2 0 0 0 681.6 483.5H318.4A21.2 21.2 0 1 0 318.4 526H681.6A21.2 21.2 0 0 0 702.8 504.7Z",
"width": 1000
},
"search": [
"link"
]
},
{
"uid": "edff4e8be7c55eb5006bf3c07ed84627",
"css": "loading",
"code": 59398,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M691.5 320.7C636.2 265.4 557.8 233.6 471.6 242.4 347 254.9 244.5 356 230.6 480.3 212 644.7 339.2 783.3 499.7 783.3 608 783.4 701 720 744.4 628.8 755.3 606.1 739 580 713.9 580 701.3 580 689.4 586.8 684 598 645.7 680.4 553.7 732.6 453.2 710.2 377.9 693.6 317.2 632.2 301.2 557 272.7 425.5 372.8 308.9 499.8 308.9 556.1 308.9 606.3 332.3 643 369.2L591.7 420.4C570.3 441.7 585.3 478.4 615.5 478.4H737.3A34 34 0 0 0 771.2 444.5V322.7C771.2 292.6 734.6 277.3 713.2 298.7Z",
"width": 1000
},
"search": [
"loading"
]
},
{
"uid": "e36ffa9338ecf20e9edff18bab26c78b",
"css": "messages",
"code": 59399,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M895.9 207C880.5 167.4 842.2 139.2 797.2 139.2H202.8C157.8 139.2 119.5 167.4 104.1 207 99.8 216.3 96.7 228.6 96.7 245.3V754.7A106.2 106.2 0 0 0 202.8 860.8H797.2A106.2 106.2 0 0 0 903.3 754.7V245.3C903.3 228.6 900.2 216.3 895.9 207ZM797.2 181.6A63 63 0 0 1 823.4 187.4 104.5 104.5 0 0 0 804.5 200.9L549.4 427.7C522.6 451.6 477.4 451.5 450.6 427.7L195.5 200.9A104.5 104.5 0 0 0 176.6 187.4 63 63 0 0 1 202.8 181.6ZM860.8 754.7A63.7 63.7 0 0 1 797.2 818.4H202.8A63.7 63.7 0 0 1 139.2 754.7V245.3A62.8 62.8 0 0 1 143 224.3C143.9 222.7 144.7 221.5 145.3 221.3A3 3 0 0 1 146.5 221.1C149.6 221.1 157.1 223.7 167.3 232.7L422.4 459.4C465.2 497.5 534.8 497.4 577.6 459.4L832.7 232.7C844.7 222 853 220.3 854.7 221.2 855.3 221.5 856.1 222.7 857 224.2A62.8 62.8 0 0 1 860.8 245.2Z",
"width": 1000
},
"search": [
"messages"
]
},
{
"uid": "1244f824558dee479548678c14b23fdc",
"css": "notifications",
"code": 59400,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M848.5 713.8L825.5 690A199.8 199.8 0 0 1 768.9 550.1V400.7C768.8 252.8 648.4 132 500 131.5L496.1 131.6C349.7 133.9 231.2 253.9 231.2 400.7V550.1A200 200 0 0 1 174.6 690L151.5 713.8A35 35 0 0 0 176.6 773.2H392.1C399 826.8 444.5 868.5 500 868.5S601 826.8 607.9 773.2H823.5A35 35 0 0 0 848.5 713.8ZM500 826.1A67 67 0 0 1 436.6 780.4H563.4A67 67 0 0 1 500 826.1ZM194.2 730.7L205 719.5A242 242 0 0 0 273.6 550.1V400.7C273.6 277.1 373.4 176.1 496.9 174H500.3C624.9 174.4 726.3 276.1 726.3 400.7V550.1A241.9 241.9 0 0 0 795 719.5L805.8 730.7Z",
"width": 1000
},
"search": [
"notifications"
]
},
{
"uid": "bf400c799f09b178126d80e4150db034",
"css": "reply",
"code": 59401,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M800.2 818.4A20.2 20.2 0 0 1 793.5 817.3L611.5 757.3A305.4 305.4 0 0 1 483.8 785.4H483.3C367.3 785.4 262.9 721.4 210.9 618.6A297.6 297.6 0 0 1 178.6 483.5V467C187.2 312.3 310.5 190.1 465.5 181.7L483.3 181.7H484.1A304.4 304.4 0 0 1 619.5 213.7C723.4 265 788 368.4 788 483.5A296.9 296.9 0 0 1 759.7 610.4L820.3 790.4A21.2 21.2 0 0 1 800.1 818.4ZM610.1 713.2A21.7 21.7 0 0 1 616.7 714.3L766.5 763.7 716.7 615.7A21.2 21.2 0 0 1 717.9 599.3 253.7 253.7 0 0 0 745.6 483.6C745.6 384.7 690 295.8 600.7 251.6A261.6 261.6 0 0 0 484.1 224H466.6C334.4 231.3 228.4 336.3 221 468.2L221 483.5V483.5A254.5 254.5 0 0 0 248.7 599.3C293.4 687.8 383.3 742.9 483.3 742.9H483.8A262.1 262.1 0 0 0 600.5 715.4 21.2 21.2 0 0 1 610.1 713.2ZM199.8 483.5H199.8Z",
"width": 1000
},
"search": [
"reply"
]
},
{
"uid": "6c4a7779a01ea357cc3a4584ab32de14",
"css": "repost",
"code": 59402,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M759.5 754.7A21.2 21.2 0 0 1 745.3 749.2L597.4 615.8A21.2 21.2 0 0 1 625.8 584.3L738.3 685.8V373.2C738.3 326.1 694.7 287.7 641.2 287.7H478.6A21.2 21.2 0 0 1 478.6 245.3H641.2C718.1 245.3 780.8 302.7 780.8 373.3V685.8L893.1 584.3A21.2 21.2 0 0 1 921.6 615.8L773.7 749.2A21.1 21.1 0 0 1 759.5 754.7ZM521.4 754.7H333.8C263 754.7 205.4 697.6 205.4 627.4V317.4L107.6 414.2A21.2 21.2 0 1 1 77.7 384.1L211.6 251.5C211.8 251.3 212 251 212.3 250.8 212.3 250.8 212.3 250.8 212.3 250.8H212.3A21.1 21.1 0 0 1 218 247.1C218 247.1 218 247.1 218 247.1H218A22.1 22.1 0 0 1 234.8 247 20.8 20.8 0 0 1 241.5 251.5L375.5 384.1A21.2 21.2 0 1 1 345.6 414.3L247.7 317.4V627.4C247.7 674.3 286.3 712.3 333.7 712.3H521.4A21.2 21.2 0 1 1 521.4 754.8Z",
"width": 1000
},
"search": [
"repost"
]
},
{
"uid": "ffa0595179adaca6f74f0a41c93981e8",
"css": "search",
"code": 59403,
"src": "custom_icons",
"selected": true,
"svg": {
"path": "M812.4 777.8L699.2 660.8A301.7 301.7 0 0 0 756.8 483.1C756.8 319.3 627.8 186 469.2 186S181.6 319.3 181.6 483.2 310.6 780.3 469.2 780.3C548.5 780.3 620.4 747 672.4 693.2L783.3 807.8A20.1 20.1 0 0 0 812.3 807.8 21.8 21.8 0 0 0 812.4 777.8ZM469.2 737.9C333.3 737.9 222.7 623.6 222.7 483.2S333.3 228.4 469.2 228.4 715.7 342.7 715.7 483.2 605.1 737.9 469.2 737.9Z",
"width": 1000
},
"search": [
"search"
]
},
{
"uid": "f85affb51c357be83d187344c8c6e35c",
"css": "diamond",
"code": 61977,
"src": "fontawesome"
},
{
"uid": "f8e8b267a9b949804f0c9dd7fed8e477",
"css": "diamond-1",
"code": 59406,
"src": "linecons"
}
]
}

View file

@ -0,0 +1,42 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Copyright (C) 2021 by original authors @ fontello.com</metadata>
<defs>
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="close" unicode="&#xe800;" d="M527 350l251 252a19 19 0 1 1-26 26l-252-251-252 251a19 19 0 0 1-26-26l251-252-251-252a19 19 0 0 1 26-26l252 251 252-251a19 19 0 0 1 26 26z" horiz-adv-x="1000" />
<glyph glyph-name="down-arrow" unicode="&#xe801;" d="M500 216c-18 0-35 9-48 23l-170 201a27 27 0 0 0 40 34l171-201c3-3 11-3 14 0l171 201a27 27 0 0 0 40-34l-170-201c-13-14-30-23-48-23z" horiz-adv-x="1000" />
<glyph glyph-name="heart" unicode="&#xe802;" d="M500 32a84 84 0 0 0-58 23l-3 3c-173 165-286 272-282 412 3 64 34 125 84 161 91 65 196 38 259-23 63 61 168 88 259 23l0 0c50-36 82-96 84-161 4-140-110-248-282-412l-3-3a83 83 0 0 0-58-23z m-145 594c-30 0-60-9-89-30-40-28-64-76-66-128-4-120 103-223 266-378l5-5c17-15 41-15 57 1l4 3c164 156 272 259 268 380-1 50-27 99-66 127-78 56-170 25-217-33l-17-20-16 20c-30 37-78 63-129 63z" horiz-adv-x="1000" />
<glyph glyph-name="heart-fill" unicode="&#xe803;" d="M746 614c-85 60-189 32-246-37-57 69-161 98-246 37-45-32-74-87-75-145-5-130 106-235 274-396l4-3a62 62 0 0 1 86 1l4 3c168 160 279 265 275 396-2 57-31 112-76 144z" horiz-adv-x="1000" />
<glyph glyph-name="home" unicode="&#xe804;" d="M824 537l-288 175a76 76 0 0 1-72 0l-287-175c-30-16-48-45-48-77v-438c0-24 20-43 45-43h170a53 53 0 0 1 53 53v189c0 51 46 92 103 92s103-41 103-92v-189a53 53 0 0 1 54-53h169c25 0 45 19 45 43v438c0 32-18 61-47 77z m5-502a13 13 0 0 0-14-13l-158 0a11 11 0 0 0-11 10v189c0 74-65 134-146 134s-146-60-146-134v-189a11 11 0 0 0-10-10l-159 0a13 13 0 0 0-13 13v425c0 16 9 31 26 40l287 175a33 33 0 0 0 30 0l288-175c16-9 26-24 26-40z" horiz-adv-x="1000" />
<glyph glyph-name="link" unicode="&#xe805;" d="M709 117h-109a21 21 0 0 0 0 42h109c105 0 191 86 191 191s-86 191-191 191h-109a21 21 0 0 0 0 42h109c129 0 233-104 233-233s-104-233-233-233z m-288 21a21 21 0 0 1-21 21h-109c-105 0-191 86-191 191s86 191 191 191h109a21 21 0 0 1 0 42h-109c-129 1-233-104-233-233s104-233 233-233h109a21 21 0 0 1 21 21z m282 207a21 21 0 0 1-21 22h-364a21 21 0 1 1 0-43h364a21 21 0 0 1 21 21z" horiz-adv-x="1000" />
<glyph glyph-name="loading" unicode="&#xe806;" d="M692 529c-56 56-134 87-220 79-125-13-227-114-241-238-19-165 108-303 269-303 108 0 201 63 244 154 11 23-5 49-30 49-13 0-25-7-30-18-38-82-130-135-231-112-75 16-136 78-152 153-28 132 72 248 199 248 56 0 106-23 143-60l-51-51c-22-22-7-58 24-58h121a34 34 0 0 1 34 34v121c0 30-36 46-58 24z" horiz-adv-x="1000" />
<glyph glyph-name="messages" unicode="&#xe807;" d="M896 643c-15 40-54 68-99 68h-594c-45 0-83-28-99-68-4-9-7-22-7-38v-510a106 106 0 0 1 106-106h594a106 106 0 0 1 106 106v510c0 16-3 29-7 38z m-99 25a63 63 0 0 0 26-5 105 105 0 0 1-18-14l-256-227c-26-24-72-23-98 0l-255 227a105 105 0 0 1-19 14 63 63 0 0 0 26 5z m64-573a64 64 0 0 0-64-63h-594a64 64 0 0 0-64 63v510a63 63 0 0 0 4 21c1 1 2 3 2 3a3 3 0 0 0 2 0c3 0 10-3 20-12l255-226c43-38 113-38 156 0l255 226c12 11 20 13 22 12 0 0 1-2 2-3a63 63 0 0 0 4-21z" horiz-adv-x="1000" />
<glyph glyph-name="notifications" unicode="&#xe808;" d="M849 136l-23 24a200 200 0 0 0-57 140v149c0 148-121 269-269 270l-4-1c-146-2-265-122-265-269v-149a200 200 0 0 0-56-140l-23-24a35 35 0 0 1 25-59h215c7-54 53-96 108-96s101 42 108 96h216a35 35 0 0 1 25 59z m-349-112a67 67 0 0 0-63 46h126a67 67 0 0 0-63-46z m-306 95l11 12a242 242 0 0 1 69 169v149c0 124 99 225 223 227h3c125 0 226-102 226-227v-149a242 242 0 0 1 69-169l11-12z" horiz-adv-x="1000" />
<glyph glyph-name="reply" unicode="&#xe809;" d="M800 32a20 20 0 0 0-6 1l-182 60a305 305 0 0 0-128-28h-1c-116 0-220 64-272 166a298 298 0 0 0-32 136v16c8 155 132 277 287 285l17 0h1a304 304 0 0 0 136-32c103-51 168-154 168-269a297 297 0 0 0-28-127l60-180a21 21 0 0 0-20-28z m-190 105a22 22 0 0 0 7-1l150-50-50 148a21 21 0 0 0 1 17 254 254 0 0 1 28 115c0 99-56 188-145 232a262 262 0 0 1-117 28h-17c-133-7-239-112-246-244l0-15v0a255 255 0 0 1 28-116c44-89 134-144 234-144h1a262 262 0 0 1 117 28 21 21 0 0 0 9 2z m-410 230h0z" horiz-adv-x="1000" />
<glyph glyph-name="repost" unicode="&#xe80a;" d="M760 95a21 21 0 0 0-15 6l-148 133a21 21 0 0 0 29 32l112-102v313c0 47-43 85-97 85h-162a21 21 0 0 0 0 43h162c77 0 140-58 140-128v-313l112 102a21 21 0 0 0 29-32l-148-133a21 21 0 0 0-14-6z m-239 0h-187c-71 0-129 57-129 128v310l-97-97a21 21 0 1 0-30 30l134 133c0 0 0 0 0 0 0 0 0 0 0 0h0a21 21 0 0 0 6 4c0 0 0 0 0 0h0a22 22 0 0 0 17 0 21 21 0 0 0 7-4l134-133a21 21 0 1 0-30-30l-98 97v-310c0-47 38-85 86-85h187a21 21 0 1 0 0-43z" horiz-adv-x="1000" />
<glyph glyph-name="search" unicode="&#xe80b;" d="M812 72l-113 117a302 302 0 0 1 58 178c0 164-129 297-288 297s-287-133-287-297 129-297 287-297c80 0 151 33 203 87l111-115a20 20 0 0 1 29 0 22 22 0 0 1 0 30z m-343 40c-136 0-246 114-246 255s110 255 246 255 247-115 247-255-111-255-247-255z" horiz-adv-x="1000" />
<glyph glyph-name="up-arrow" unicode="&#xe80c;" d="M987 613a21 21 0 0 1-20 13h-255a21 21 0 0 1 0-42h204l-339-340a18 18 0 0 0-26 0l-157 157a61 61 0 0 1-85 0l-291-291a21 21 0 1 1 30-30l291 291a18 18 0 0 0 25 0l157-157a61 61 0 0 1 86 0l339 340v-204a21 21 0 1 1 42 0v255a21 21 0 0 1-1 8z" horiz-adv-x="1000" />
<glyph glyph-name="wallet" unicode="&#xe80d;" d="M710 335a60 60 0 1 1 60-60 60 60 0 0 1-60 60z m103 231v36a115 115 0 0 1-134 113l-489-81c-57-9-101-55-101-105v-439a106 106 0 0 1 106-107h610a106 106 0 0 1 107 107v370c0 56-44 102-99 106z m-616 26l489 81a72 72 0 0 0 84-71v-36h-575a106 106 0 0 1-59-18c9 21 33 40 61 44z m672-502a64 64 0 0 0-64-64h-610a64 64 0 0 0-64 64v370a64 64 0 0 0 64 64h610a64 64 0 0 0 64-64z" horiz-adv-x="1000" />
<glyph glyph-name="diamond-1" unicode="&#xe80e;" d="M0 502q0 28 18 45l160 158q17 20 43 20l558 0q26 0 43-20l160-158q18-17 18-43 0-23-16-43l-437-465q-20-21-47-21t-47 21l-437 465q-16 18-16 41z m63 4l134 0 84 84-72 61z m27-31l307-328-196 328-111 0z m146 0l231-383-76 383-155 0z m4 31l143 0-78 65z m2 156l61-50 51 50-112 0z m84-70l80-66 71 58-86 71z m96-117l78-389 78 389-156 0z m8 31l140 0-70 57z m0 156l70-58 68 58-138 0z m95-78l69-58 80 66-65 63z m8-492l231 383-155 0z m71 55l306 328-111 0z m13 359l143 0-65 65z m29 156l51-50 61 50-112 0z m73-72l84-84 133 0-145 145z" horiz-adv-x="1000" />
<glyph glyph-name="diamond" unicode="&#xf219;" d="M118 421l348-371-167 371h-181z m453-430l195 430h-389z m-271 502l114 214h-146l-161-214h193z m377-443l348 371h-181z m-296 443h381l-114 214h-153z m462 0h193l-161 214h-146z m78 271l215-286q7-10 7-23t-10-22l-535-572q-10-11-27-11t-26 11l-535 572q-9 9-10 22t7 23l215 286q10 15 28 15h643q18 0 28-15z" horiz-adv-x="1142.9" />
</font>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
example/frontend/src/vendor/fontello.ttf vendored Normal file

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more