Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Zennies for Zingo address #668

Merged
merged 12 commits into from
Jul 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions android/app/src/main/java/org/ZingoLabs/Zingo/RPCModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,18 @@ class RPCModule internal constructor(private val reactContext: ReactApplicationC
promise.resolve(resp)
}

@ReactMethod
fun getZenniesDonationAddress(promise: Promise) {
// Log.i("MAIN", "Initialize Light Client")

uniffi.zingo.initLogging()

// Initialize Light Client
val resp = uniffi.zingo.getZenniesForZingoDonationAddress()

promise.resolve(resp)
}

@ReactMethod
fun getValueTransfersList(promise: Promise) {
// Log.i("MAIN", "Initialize Light Client")
Expand Down
19 changes: 11 additions & 8 deletions app/LoadedApp/LoadedApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,11 @@ export default function LoadedApp(props: LoadedAppProps) {
setBackground(backgroundJson);
}

// reading the address book
const ab = await AddressBookFileImpl.readAddressBook();
// adding `Zenny Tips` address always.
const ab = await AddressBookFileImpl.writeAddressBookItem(
translate('zenny-tips-ab') as string,
await Utils.getZenniesDonationAddress(server.chainName),
);
setAddressBook(ab);

setLoading(false);
Expand Down Expand Up @@ -914,8 +917,8 @@ export class LoadedAppClass extends Component<LoadedAppClassProps, LoadedAppClas
sendTransaction = async (setSendProgress: (arg0: SendProgressClass) => void): Promise<String> => {
try {
// Construct a sendJson from the sendPage state
const { sendPageState, uaAddress, addresses, server, donation, translate } = this.state;
const sendJson = await Utils.getSendManyJSON(sendPageState, uaAddress, addresses, server, donation, translate);
const { sendPageState, uaAddress, addresses, server, donation } = this.state;
const sendJson = await Utils.getSendManyJSON(sendPageState, uaAddress, addresses, server, donation);
const txid = await this.rpc.sendTransaction(sendJson, setSendProgress);

return txid;
Expand Down Expand Up @@ -1038,7 +1041,7 @@ export class LoadedAppClass extends Component<LoadedAppClassProps, LoadedAppClas
let update = false;
if (
this.state.sendPageState.toaddr.to &&
this.state.sendPageState.toaddr.to !== (await Utils.getDonationAddress(this.state.server.chainName))
this.state.sendPageState.toaddr.to !== (await Utils.getNymDonationAddress(this.state.server.chainName))
) {
await ShowAddressAlertAsync(this.state.translate)
.then(async () => {
Expand All @@ -1055,9 +1058,9 @@ export class LoadedAppClass extends Component<LoadedAppClassProps, LoadedAppClas
let uriToAddr: ToAddrClass = new ToAddrClass(0);
const to = new ToAddrClass(Utils.getNextToAddrID());

to.to = await Utils.getDonationAddress(this.state.server.chainName);
to.amount = Utils.getDefaultDonationAmount();
to.memo = this.state.translate('loadedapp.nymmemo') as string;
to.to = await Utils.getNymDonationAddress(this.state.server.chainName);
to.amount = Utils.getNymDonationAmount();
to.memo = Utils.getNymDonationMemo(this.state.translate);
to.includeUAMemo = true;

uriToAddr = to;
Expand Down
5 changes: 3 additions & 2 deletions app/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"confirm": "Confirm",
"menudrawer-acc": "Open Menu Drawer",
"menu-acc": "Open Menu",
"donation": "Thanks for supporting ZingoLabs!",
"donation": "Donation to Zingo!\nThanks for supporting ZingoLabs!",
"zenny-tips-ab": "Zenny Tips",
"nym-donation": "I need Nym network security!",
"restarting": "Error connecting to the Server, the App will restart in a few seconds.",
"change-privacy": "New privacy policy: ",
"warning-binance": "WARNING: Binance is collecting and holding user funds without timely recourse. Do NOT deposit into Binance from this Wallet.",
Expand Down Expand Up @@ -132,7 +134,6 @@
"selectingserver": "Determining the best lightwalletd.",
"selectingserversame": "Your actual server is the most optimized one already.",
"selectingserverbest": "In this moment this is the most optimized server:",
"nymmemo": "I need Nym network security",
"incoming-funds": "Incoming funds\n",
"valuetransfer-confirmed": "Transaction confirmed\n",
"payment-made": "Payment made\n",
Expand Down
5 changes: 3 additions & 2 deletions app/translations/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"confirm": "Confirmar",
"menudrawer-acc": "Abrir Menú Lateral",
"menu-acc": "Abrir Menú",
"donation": "Gracias por apoyar ZingoLabs!",
"donation": "¡Donación a Zingo!\n¡Gracias por apoyar a ZingoLabs!",
"zenny-tips-ab": "Zenny Propinas",
"nym-donation": "¡Necesito seguridad de red Nym!",
"restarting": "Error conectando con el servidor, la Aplicación se reiniciará en breves segundos.",
"change-privacy": "Nueva Política de Privacidad: ",
"warning-binance": "ADVERTENCIA: Binance recopila y retiene los fondos de los usuarios sin un recurso oportuno. NO deposite en Binance desde este Monedero.",
Expand Down Expand Up @@ -132,7 +134,6 @@
"selectingserver": "Determinando el mejor lightwalletd.",
"selectingserversame": "Su servidor actual ya es el más optimizado.",
"selectingserverbest": "En este momento este es el servidor más optimizado:",
"nymmemo": "Necesito seguridad de red Nym",
"incoming-funds": "Fondos entrantes\n",
"valuetransfer-confirmed": "Transacción confirmada\n",
"payment-made": "Pago realizado\n",
Expand Down
5 changes: 3 additions & 2 deletions app/translations/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"confirm": "Confirmar",
"menudrawer-acc": "Abrir Menu Lateral",
"menu-acc": "Abrir Menu",
"donation": "Obrigado por apoiar a ZingoLabs!",
"donation": "Doação para o Zingo!\nObrigado por apoiar o ZingoLabs!",
"zenny-tips-ab": "Zenny Gorjetas",
"nym-donation": "Eu preciso de segurança de rede Nym!",
"restarting": "Erro ao conectar ao servidor, o aplicativo será reiniciado em alguns segundos.",
"change-privacy": "Nova política de privacidade: ",
"warning-binance": "AVISO: A Binance está coletando e mantendo fundos dos usuários sem recurso oportuno. NÃO deposite na Binance a partir desta Carteira.",
Expand Down Expand Up @@ -132,7 +134,6 @@
"selectingserver": "Determinando a melhor lightwalletd.",
"selectingserversame": "Seu servidor atual já é o mais otimizado.",
"selectingserverbest": "Neste momento ele é o servidor mais otimizado:",
"nymmemo": "Eu preciso de segurança de rede Nym",
"incoming-funds": "Fundos recebidos\n",
"valuetransfer-confirmed": "Transação confirmada\n",
"payment-made": "Pagamento efetuado\n",
Expand Down
5 changes: 3 additions & 2 deletions app/translations/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"confirm": "Подтвердить",
"menudrawer-acc": "Открыть панель меню",
"menu-acc": "Открыть меню",
"donation": "Спасибо за поддержку ZingoLabs!",
"donation": "Пожертвование в пользу Zingo!\nСпасибо за поддержку ZingoLabs!",
"zenny-tips-ab": "Zenny советы",
"nym-donation": "Мне нужна сетевая безопасность Nym!",
"restarting": "Ошибка подключения к Серверу, приложение перезапустится через несколько секунд.",
"change-privacy": "Новая политика конфиденциальности: ",
"warning-binance": "ВНИМАНИЕ: Binance собирает и удерживает средства пользователей без своевременного обращения к ним. НЕ делайте депозиты на Binance с этого кошелька.",
Expand Down Expand Up @@ -132,7 +134,6 @@
"selectingserver": "Определение ближайшего сервера.",
"selectingserversame": "Ваш текущий сервер является ближайшим.",
"selectingserverbest": "В этот момент его самый оптимизированный сервер:",
"nymmemo": "Мне нужна сетевая безопасность Nym",
"incoming-funds": "Входящие средства\n",
"valuetransfer-confirmed": "Транзакция подтверждена\n",
"payment-made": "Платеж произведен\n",
Expand Down
59 changes: 50 additions & 9 deletions app/utils/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export default class Utils {
return Utils.nextToAddrID++;
}

// DONATION TO ZINGOLABS
static async getDonationAddress(chainName: ChainNameEnum): Promise<string> {
// donations only for mainnet.
if (chainName === ChainNameEnum.mainChainName) {
Expand All @@ -117,16 +118,54 @@ export default class Utils {
return '';
}

static getDefaultDonationAmount(): string {
static getDonationAmount(): string {
const { decimalSeparator } = getNumberFormatSettings();

return '0' + decimalSeparator + '01';
}

static getDefaultDonationMemo(translate: (key: string) => TranslateType): string {
static getDonationMemo(translate: (key: string) => TranslateType): string {
return translate('donation') as string;
}

// ZENNIES FOR ZINGO
static async getZenniesDonationAddress(chainName: ChainNameEnum): Promise<string> {
// donations only for mainnet.
if (chainName === ChainNameEnum.mainChainName) {
// UA -> we need a fresh one.
const ua: string = await RPCModule.getZenniesDonationAddress();
return ua;
}
return '';
}

static getZenniesDonationAmount(): string {
const { decimalSeparator } = getNumberFormatSettings();

return '0' + decimalSeparator + '01';
}

// NYM
static async getNymDonationAddress(chainName: ChainNameEnum): Promise<string> {
// donations only for mainnet.
if (chainName === ChainNameEnum.mainChainName) {
// UA -> we need a fresh one.
const ua: string = await RPCModule.getDonationAddress();
return ua;
}
return '';
}

static getNymDonationAmount(): string {
const { decimalSeparator } = getNumberFormatSettings();

return '0' + decimalSeparator + '01';
}

static getNymDonationMemo(translate: (key: string) => TranslateType): string {
return translate('nym-donation') as string;
}

static utf16Split(s: string, chunksize: number): string[] {
const ans = [];

Expand Down Expand Up @@ -198,15 +237,17 @@ export default class Utils {
addresses: AddressClass[],
server: ServerType,
donation: boolean,
translate: (key: string) => TranslateType,
): Promise<SendJsonToTypeType[]> {
let donationAddress: boolean = false;
const json: Promise<SendJsonToTypeType[][]> = Promise.all(
[sendPageState.toaddr].flatMap(async (to: ToAddrClass) => {
const memo = `${to.memo || ''}${to.includeUAMemo ? '\nReply to: \n' + uaAddress : ''}`;
const amount = parseInt((Utils.parseStringLocaleToNumberFloat(to.amount) * 10 ** 8).toFixed(0), 10);

donationAddress = to.to === (await Utils.getDonationAddress(server.chainName));
donationAddress =
to.to === (await Utils.getDonationAddress(server.chainName)) ||
to.to === (await Utils.getZenniesDonationAddress(server.chainName)) ||
to.to === (await Utils.getNymDonationAddress(server.chainName));

if (memo === '') {
return [{ address: to.to, amount } as SendJsonToTypeType];
Expand Down Expand Up @@ -240,16 +281,16 @@ export default class Utils {
const donationTransaction: SendJsonToTypeType[] = [];

// we need to exclude 2 use cases:
// 1. send to self (make no sense to do a donation here)
// 2. send to donation UA (make no sense to do a double donation)
// 2. send to one of our donation UA's
// (make no sense to do a double donation)
if (donation && server.chainName === ChainNameEnum.mainChainName && !donationAddress) {
donationTransaction.push({
address: await Utils.getDonationAddress(server.chainName),
address: await Utils.getZenniesDonationAddress(server.chainName),
amount: parseInt(
(Utils.parseStringLocaleToNumberFloat(Utils.getDefaultDonationAmount()) * 10 ** 8).toFixed(0),
(Utils.parseStringLocaleToNumberFloat(Utils.getZenniesDonationAmount()) * 10 ** 8).toFixed(0),
10,
),
memo: Utils.getDefaultDonationMemo(translate) + '\n' + translate('settings.donation-title'),
memo: '', // zancas decision to not leak info with no reason.
});
}

Expand Down
58 changes: 45 additions & 13 deletions components/AddressBook/AddressBook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import AddressBookFileImpl from './AddressBookFileImpl';
import RPC from '../../app/rpc';
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
import { faAnglesUp } from '@fortawesome/free-solid-svg-icons';
import Utils from '../../app/utils';

type AddressBookProps = {
closeModal: () => void;
Expand All @@ -45,13 +46,14 @@ type AddressBookProps = {

const AddressBook: React.FunctionComponent<AddressBookProps> = ({ closeModal, setAddressBook, setSendPageState }) => {
const context = useContext(ContextAppLoaded);
const { translate, language, addressBook, addressBookCurrentAddress, addressBookOpenPriorModal } = context;
const { translate, language, addressBook, addressBookCurrentAddress, addressBookOpenPriorModal, server } = context;
const { colors } = useTheme() as unknown as ThemeType;
moment.locale(language);

const [numAb, setNumAb] = useState<number>(50);
const [loadMoreButton, setLoadMoreButton] = useState<boolean>(false);
const [addressBookSorted, setAddressBookSorted] = useState<AddressBookFileClass[]>([]);
const [addressBookProtected, setAddressBookProtected] = useState<AddressBookFileClass[]>([]);

const [currentItem, setCurrentItem] = useState<number | null>(null);
const [titleViewHeight, setTitleViewHeight] = useState<number>(0);
Expand All @@ -64,20 +66,29 @@ const AddressBook: React.FunctionComponent<AddressBookProps> = ({ closeModal, se
useScrollToTop(scrollViewRef);

const fetchAddressBookSorted = useMemo(async () => {
// excluding this address from the list
const zennyTips = await Utils.getZenniesDonationAddress(server.chainName);
return addressBook
.filter((ab: AddressBookFileClass) => ab.address !== zennyTips)
.sort((a, b) => {
const nA = a.label.toUpperCase();
const nB = b.label.toUpperCase();
if (nA < nB) {
return -1;
} else if (nA > nB) {
return 1;
} else {
return 0;
}
const aLabel = a.label;
const bLabel = b.label;
return aLabel.localeCompare(bLabel);
})
.slice(0, numAb);
}, [addressBook, numAb]);
}, [addressBook, numAb, server.chainName]);

const fetchAddressBookProtected = useMemo(async () => {
// only protected address to use internally ZingoLabs.
const zennyTips = await Utils.getZenniesDonationAddress(server.chainName);
return addressBook
.filter((ab: AddressBookFileClass) => ab.address === zennyTips)
.sort((a, b) => {
const aLabel = a.label;
const bLabel = b.label;
return aLabel.localeCompare(bLabel);
});
}, [addressBook, server.chainName]);

// because this screen is fired from more places than the menu.
useEffect(() => {
Expand All @@ -87,8 +98,10 @@ const AddressBook: React.FunctionComponent<AddressBookProps> = ({ closeModal, se
useEffect(() => {
(async () => {
const abs = await fetchAddressBookSorted;
const abp = await fetchAddressBookProtected;
setLoadMoreButton(numAb < (abs.length || 0));
setAddressBookSorted(abs);
setAddressBookProtected(abp);
// find the current address
if (addressBookCurrentAddress) {
const index: number = abs.findIndex((i: AddressBookFileClass) => i.address === addressBookCurrentAddress);
Expand All @@ -100,7 +113,7 @@ const AddressBook: React.FunctionComponent<AddressBookProps> = ({ closeModal, se
setCurrentItem(index);
}
})();
}, [addressBookCurrentAddress, fetchAddressBookSorted, numAb]);
}, [addressBookCurrentAddress, fetchAddressBookProtected, fetchAddressBookSorted, numAb]);

useEffect(() => {
const keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', () => {
Expand Down Expand Up @@ -225,7 +238,7 @@ const AddressBook: React.FunctionComponent<AddressBookProps> = ({ closeModal, se
doAction={doAction}
/>
)}
{addressBookSorted.length === 0 && currentItem !== -1 && (
{!addressBookCurrentAddress && addressBookSorted.length === 0 && currentItem !== -1 && (
<View
style={{
height: 150,
Expand Down Expand Up @@ -277,6 +290,25 @@ const AddressBook: React.FunctionComponent<AddressBookProps> = ({ closeModal, se
</View>
);
})}
{!addressBookCurrentAddress &&
addressBookProtected.flatMap((aBItem, index) => {
return (
<View key={`container-${index}-${aBItem.label}`}>
<AbSummaryLine
index={index}
key={`line-${index}-${aBItem.label}`}
item={aBItem}
setCurrentItem={setCurrentItem}
setAction={setAction}
setSendPageState={setSendPageState}
closeModal={closeModal}
handleScrollToTop={handleScrollToTop}
doAction={doAction}
addressProtected={true}
/>
</View>
);
})}
{loadMoreButton ? (
<View
style={{
Expand Down
Loading
Loading